What Is a HAR File? β Definition and How It Works
Learn what a HAR file records, how to capture one, why it is the fastest route to a site's private API, and its secret risk.
A HAR file β HTTP Archive β is a JSON record of every request a browser made while loading a page: URLs, methods, headers, bodies, timings, and status codes.
1. What It Contains
{
"log": {
"version": "1.2",
"entries": [
{
"startedDateTime": "2026-08-18T14:00:00.000Z",
"time": 243,
"request": {
"method": "POST",
"url": "https://api.example.com/v2/search",
"headers": [{"name": "x-api-token", "value": "β¦"}],
"postData": {"mimeType": "application/json", "text": "{\"q\":\"keyboard\"}"}
},
"response": {"status": 200, "content": {"size": 18432, "mimeType": "application/json"}},
"timings": {"dns": 2, "connect": 31, "ssl": 18, "wait": 180, "receive": 12}
}
]
}
}
Every entry pairs a request with its response and a timing breakdown.
2. Why It Is the Fastest Route to a Private API
Loading a page in a browser and exporting the HAR shows you every call the page's own JavaScript made β including the JSON endpoints behind the rendered content.
That is usually far quicker than reading minified client code, and it gives you the exact request: method, path, query parameters, headers, and body. Reproducing a JSON endpoint directly then removes the browser from your pipeline entirely.
The workflow:
- Open dev tools, Network tab, clear it.
- Perform the action whose data you want.
- Filter to XHR/fetch.
- Find the response containing the data.
- Export HAR, or copy that single request.
- Reproduce it outside the browser and confirm it still works.
Step 6 is the one that matters β many such requests carry a signature, nonce, or token that must be understood before the call is reproducible.
3. Capturing One Programmatically
context = browser.new_context(record_har_path="capture.har", record_har_content="omit")
page = context.new_page()
page.goto("https://example.com/search?q=keyboard")
page.wait_for_load_state("networkidle")
context.close() # the HAR is written on close
record_har_content="omit" keeps response bodies out of the file, which shrinks it enormously and removes most of the sensitive content. Use "embed" only when you actually need the bodies.
The HAR is written when the context closes β a script that exits without closing produces no file, which is a common surprise.
4. Analysing One
import json, collections
har = json.load(open("capture.har", encoding="utf-8"))
entries = har["log"]["entries"]
by_type = collections.Counter(e["response"]["content"].get("mimeType", "?") for e in entries)
json_calls = [e for e in entries
if "json" in e["response"]["content"].get("mimeType", "")
and e["response"]["status"] == 200]
print(f"{len(entries)} requests; {len(json_calls)} JSON responses")
for e in sorted(json_calls, key=lambda x: -x["response"]["content"]["size"])[:5]:
print(f" {e['response']['content']['size']:>8} B {e['request']['method']} {e['request']['url'][:90]}")
Sorting JSON responses by size is the shortcut: the endpoint holding the data you want is almost always among the largest.
5. HAR Files Are Full of Secrets
This is the part that gets skipped. A HAR captured from an authenticated session contains session cookies, bearer tokens, API keys, CSRF tokens, and personal data β in plaintext, in a JSON file that looks innocuous.
Consequences to take seriously: never commit a HAR to a repository, never attach one to an issue or a support ticket without sanitising it, and never share one in chat. Treat it exactly as you would a password file β restricted permissions, deleted when done.
If you must share one, strip it:
SENSITIVE = {"cookie", "set-cookie", "authorization", "x-api-token", "x-csrf-token"}
for e in entries:
for section in ("request", "response"):
for h in e[section].get("headers", []):
if h["name"].lower() in SENSITIVE:
h["value"] = "REDACTED"
e["request"].pop("postData", None)
6. The Timing Data Is Useful Too
Each entry's timings breaks down DNS, connect, TLS, wait, and receive. That makes a HAR a performance record as well as a request log β it tells you whether a slow page is slow because of the server, the network, or the sheer number of requests.
For collection work the request count is often the finding: a page making 300 requests is one where blocking images and fonts will transform throughput.
7. Summary
A HAR file is a JSON archive of every browser request and response for a session, including headers, bodies, and timings.
It is the fastest way to discover the JSON endpoints behind a rendered page β export it, sort JSON responses by size, and reproduce the interesting call outside the browser β but it captures cookies, tokens, and keys in plaintext, so it must be handled and sanitised as a credential file rather than shared casually.