Use HAR to audit whether your JMeter script covers what the browser actually loads. Don't compare the numbers. Compare the coverage
JMeter says your API responds in 350ms. The browser says the same call took 500ms. Which one do you trust?
Both — they're measuring different things:
| JMeter | HAR | |
|---|---|---|
| Measures | How long each scripted request took | How long the user actually waited |
| Sees | What you explicitly scripted | Everything the browser fired — including 3rd party scripts, lazy loads, render-triggered calls |
| When slower | Backend under concurrent load — DB contention, cold caches, GC pauses | Browser overhead — DNS, SSL, connection limits, real network |
Passing your JMeter test doesn't mean your users are happy. This tool bridges the gap.
Step 1 — Export a HAR file from Chrome/Firefox
- Open DevTools → Network tab
- Navigate through your app 2–3 times (warm cache = realistic returning user)
- Right-click any request → Save all as HAR with content
Step 2 — Export a JMeter Summary Report CSV
- Add a Summary Report listener to your test plan
- Run your test
- Right-click the Summary Report → Save Table Data → save as
.csv
Step 3 — Run the comparison
python har_vs_jmeter.py your_file.har summary_report.csv report.htmlOpen report.html — done.
- 4 stat cards — HAR total load time, request count, JMeter samplers, matched count
- Request-level comparison table — HAR time vs JMeter avg, diff, dual bar chart, match score
- Unmatched HAR requests — 3rd party scripts, fonts, ad networks the browser loaded that JMeter never saw
- Unmatched JMeter samplers — samplers with no HAR equivalent
- "Why the diff?" reference — built into every report, explains whether browser overhead or backend load is the likely cause
- Python 3.7+ (standard library only — no
pip installneeded) - A
.harfile exported from Chrome or Firefox DevTools - A JMeter Summary Report CSV (exported from the Summary Report listener)
HAR requests are matched to JMeter sampler labels by URL path similarity.
| HAR URL | JMeter Label | Match |
|---|---|---|
/api/session |
/api/session |
✅ Exact (score 100) |
/api/session |
/api/session-1 |
✅ Recorder suffix auto-stripped |
/SearchHotel.php |
/SearchHotel.php-85 |
✅ Recorder counter stripped |
/api/session (×2 in HAR) |
/api/session |
✅ Both HAR hits matched (many-to-one) |
ads.example.net/ad.js |
— | → Unmatched HAR (3rd party) |
The examples/ folder has a ready-to-use demo set:
| File | Description |
|---|---|
demo.har |
10 browser requests — 3 APIs + static assets + a slow 900ms 3rd-party ad script |
demo_summary.csv |
JMeter Summary Report for the 3 API samplers |
demo_test.jmx |
Minimal JMeter test plan matching the HAR |
Try it:
python har_vs_jmeter.py examples/demo.har examples/demo_summary.csv examples/demo_report.htmlHAR > JMeter — the browser pays a tax JMeter doesn't
- DNS + SSL/TLS handshake (JMeter reuses keep-alive connections)
- Render-blocking dependencies
- Per-host connection limits (~6 concurrent)
- Real network conditions — latency, packet loss on the user's actual connection
- 3rd party scripts you never scripted
JMeter > HAR — the backend pays a tax HAR doesn't
- Concurrent load — many virtual users hammering the backend simultaneously
- DB connection pool exhaustion
- Lock contention — concurrent writes cause locks a single session never triggers
- Cold vs warm caches under load
- GC pauses / CPU saturation
A JMeter GUI Listener plugin is also available in Releases for those who prefer a UI wrapper inside JMeter.
Note: The standalone Python script above is the recommended approach. The plugin wraps the same Python engine — the standalone script is simpler and more reliable for most workflows.
HAR_vs_Jmeter/
├── har_vs_jmeter.py ← main Python script (run this)
├── README.md
├── examples/
│ ├── demo.har
│ ├── demo_summary.csv
│ └── demo_test.jmx
└── plugin/ ← optional JMeter GUI plugin
├── pom.xml
└── src/
Visvashwarr Venugopal — Performance Engineer, 11+ years across Oracle and TCS. Now freelancing.
- 🔗 LinkedIn: linkedin.com/in/visvashwarrvenugopal
MIT — free to use, modify, and distribute. Attribution appreciated.