Jitsumi
Back to the blog

Before You Share a HAR File, Check What Your Browser Recorded

A HAR file can expose URLs, authentication details and response data. Capture a short browser trace, review it locally and share only what support needs.

An illustrated HTTP network-log document with several redacted data fields beside a padlocked shield.

Someone from support asks for a HAR file to investigate a broken checkout, a failed login or an error that only appears in your browser. You open Developer Tools, record the problem and save the file. The easy part is finished; the important question comes next: what else did the browser record?

The safest approach is to capture only the failing action, use a sanitised export when your browser offers one, review the resulting file locally and send it only through an appropriate support channel. A button labelled “sanitised” reduces some risks; it does not guarantee that every account identifier, personal detail or secret has disappeared.

This guide covers desktop Google Chrome, Microsoft Edge and Firefox, using their documented Network tools as of 1 November 2026. It also includes an optional Python 3.10+ script for a first-pass local review. The script was exercised against a synthetic example, not real customer traffic. It is a triage aid, not a redaction tool or a certificate of safety.

What is inside a HAR file?

HAR stands for HTTP Archive. It is a JSON document describing recorded web requests and responses. Support teams use the request sequence, HTTP status codes, timing and response details to work out where a browser interaction failed.

That same detail creates a privacy problem. The HAR 1.2 field specification defines places for full request URLs, query parameters, cookies, headers, submitted data and response bodies. Whether a particular export includes a given field or its value depends on the browser, its settings and what was recorded.

For example, a troubleshooting trace might reveal an email address in a request URL, an API key in a custom header, a form submission, or account details returned by a server. A network log is not a password list, but there is no reason to assume it contains only harmless technical information. Microsoft warns that browser traces can contain authentication tokens when describing how to collect them for support.

Here is a practical map of the fields to inspect. The names are HAR field paths, not promises that every browser populates them.

HAR location

Why it can be sensitive

What to inspect

request.url and request.queryString

Paths and parameters may include account IDs, email addresses, one-time codes or tokens.

Full URL, including query string; compare URL and parsed query fields.

request.headers and response.headers

Standard authentication headers and application-specific headers can carry secrets.

Cookie, Set-Cookie, Authorization and any custom header values.

request.cookies and response.cookies

Session or tracking cookies may identify a person or enable account access.

All cookie objects that remain after export; do not assume they were removed.

request.postData

Form values, uploaded data or JSON payloads may include private information.

text, params, filenames and encoded payloads when present.

response.content and response.redirectURL

Response bodies can contain personal records; redirects can carry codes or identifiers.

content.text, content.encoding and the redirect destination.

One easily missed distinction: a sensitive value can appear more than once. Removing a token from a header does not remove a copy embedded in a URL, JSON request body or server response. And a response body can contain personal details even when the preceding request used no obvious authentication header.

“Sanitised” does not mean “anonymous”

Google's Chrome DevTools Network reference describes a default HAR (sanitized) export that excludes sensitive headers such as Cookie, Set-Cookie and Authorization. It also documents a separate with sensitive data option that requires an explicit preference.

Microsoft's Edge Network reference describes the same distinction. These are useful protections against accidental sharing of common authentication headers.

They are not a universal guarantee. Neither description says that sanitisation removes every sensitive query parameter, response body, custom application header, email address or account identifier. It would be unsafe to extend the documented exclusion to fields the vendor has not promised to remove.

Firefox's Network Monitor documentation describes Save All as HAR and Copy All as HAR. That page does not document an equivalent promise of sanitising the exported HAR. Treat the file as potentially sensitive and inspect what your actual browser version exported rather than assuming its behaviour matches Chrome's.

If you are troubleshooting someone else's account or an organisation's production system, also follow that account owner's data-handling rules. A HAR may contain information that you are not authorised to disclose to an external support provider.

Record only the problem, not your entire browsing session

The best privacy control often happens before export. A short capture has fewer opportunities to collect irrelevant requests and secrets.

Start by asking support what they really need: the failing URL and status, a screenshot of the Network panel, a short HAR from one action, or a full session trace. If a screenshot or a single redacted response is enough, you may not need to send a complete HAR.

When a HAR is necessary, use this sequence:

  1. Choose a suitable test session. If the issue can be reproduced with non-sensitive example data or a disposable test account, prefer that. Do not invent test credentials or weaken production access merely to get a cleaner file.
  2. Open Developer Tools and the Network panel. You can usually open Developer Tools with F12 on Windows or Linux, or by choosing Inspect from the page's context menu. Find the Network tool.
  3. Clear existing requests. Use the Network panel's clear control so the capture begins with the relevant action rather than earlier browsing. Keep recording enabled.
  4. Enable persistence only if needed. Chrome and Edge call this Preserve log; Firefox uses Persist Logs. Use it when the failure crosses a navigation or redirect, because otherwise the earlier request list may disappear. Clear the log first so persistence does not retain unrelated activity.
  5. Reproduce the issue once. Note the approximate time and the action that produced the error. Avoid opening unrelated accounts, inboxes or settings pages while recording.
  6. Stop recording and export the appropriate file. In Chrome, use Export HAR (sanitized) or right-click a request and choose Save all listed as HAR (sanitized). Edge also offers Export HAR (sanitized). In Firefox, use the Network Monitor's actions menu and Save All as HAR.
  7. Keep the file local until you have reviewed it. Do not paste the raw contents into a public issue tracker, chat room or online HAR viewer just to see what's inside.

The exact position of export buttons may change with browser builds or Developer Tools layouts. The current Chrome instructions, Edge instructions and Firefox toolbar guide show their respective controls.

If the actual error is a CORS failure, first inspect the failed OPTIONS request and relevant response headers. Jitsumi's guide to tracing CORS preflights and credential checks explains what those requests mean. You may be able to describe the failure precisely without circulating an entire authenticated session.

Review the exported JSON before you share it

A .har file is structured text. Open a local copy in a trusted text editor that can handle its size, such as a desktop code editor, and keep the original intact. Do not rename the extension and assume that changes its contents.

Read the request URLs first. The hostname, path and query string can reveal a private project, internal address, account identifier, email address or token. Then look through request and response headers, cookies, submitted data and returned content. Search for likely terms such as authorization, cookie, token, secret, apikey, password, email and session, but do not treat a search with zero matches as proof of safety. An application might use a field called id, code, state or an unremarkable custom header for sensitive information.

The HAR specification permits response text to be stored as normal text or encoded, for example with base64. That means a plain text search may miss content inside encoded bodies. If you are not comfortable inspecting a large or unfamiliar trace, ask support for a narrower capture or a secure way to have it reviewed by someone authorised.

Worked example: the ordinary-looking header

Imagine a *fictional* login-related request in a HAR:

{
  "request": {
    "url": "https://example.invalid/account?session=EXAMPLE_ONLY",
    "headers": [
      {"name": "X-Session", "value": "EXAMPLE_ONLY"}
    ],
    "postData": {
      "mimeType": "application/json",
      "text": "{\"email\":\"[email protected]\"}"
    }
  },
  "response": {
    "content": {
      "mimeType": "application/json",
      "text": "{\"accountId\":123}"
    }
  }
}

All values above are fictional placeholders; they are not functioning credentials. Even if the browser removed Authorization and Cookie, the URL's session parameter, the custom X-Session header and the JSON bodies would still deserve review if they appeared in the exported file.

This is why a review should follow the structure of the HAR, not just look for one known header name. Sanitising a common header and removing all identifying information are different operations.

Optional: flag likely risk locations without printing their values

If you regularly inspect HAR files, this small local Python script can identify entries containing certain high-risk fields. It prints field categories and entry numbers only, not URLs, header values, cookie contents or response bodies. It does not contact a service or upload the file.

Save it as har_audit_local.py somewhere you control. You need Python 3.10 or later; there are no third-party packages to install.

"""Local triage for HAR 1.2-style JSON. Never prints captured values.
Python 3.10+; standard library only. NOT a sanitizer.
"""
import json
import sys
from pathlib import Path
from urllib.parse import urlsplit


def inspect_har(path: Path) -> int:
    if path.stat().st_size > 25_000_000:
        raise ValueError("HAR exceeds the 25 MB review limit")
    with path.open("r", encoding="utf-8") as f:
        doc = json.load(f)
    entries = doc.get("log", {}).get("entries", [])
    if not isinstance(entries, list):
        raise ValueError("Expected log.entries to be an array")
    print(f"Entries: {len(entries)}. Review every URL and header value manually.")
    flagged = 0
    for i, entry in enumerate(entries, 1):
        if not isinstance(entry, dict):
            raise ValueError(f"Entry {i} is not an object")
        req = entry.get("request") or {}
        res = entry.get("response") or {}
        if not isinstance(req, dict) or not isinstance(res, dict):
            raise ValueError(f"Entry {i} has an invalid request/response")
        flags = []
        url = req.get("url", "")
        if isinstance(url, str) and urlsplit(url).query:
            flags.append("URL query")
        if req.get("queryString"):
            flags.append("queryString")
        for label, side in (("request", req), ("response", res)):
            if side.get("cookies"):
                flags.append(f"{label} cookies")
            headers = side.get("headers") or []
            if isinstance(headers, list):
                risky = ("authorization", "cookie", "token", "api-key",
                         "api_key", "secret")
                if any(isinstance(h, dict) and any(
                    k in str(h.get("name", "")).lower() for k in risky
                ) for h in headers):
                    flags.append(f"{label} sensitive-looking header name")
        post = req.get("postData") or {}
        if isinstance(post, dict) and (
            post.get("text") is not None or post.get("params")
        ):
            flags.append("request body")
        content = res.get("content") or {}
        if isinstance(content, dict) and content.get("text") is not None:
            flags.append("response body")
        if flags:
            flagged += 1
            if flagged <= 25:
                print(f"Entry {i}: {', '.join(dict.fromkeys(flags))}")
    if flagged > 25:
        print(f"... plus {flagged - 25} other flagged entries (not shown)")
    print("This is an incomplete triage, not proof that the HAR is safe to share.")
    return flagged


if __name__ == "__main__":
    if len(sys.argv) != 2:
        raise SystemExit("Usage: python har_audit_local.py path/to/file.har")
    try:
        inspect_har(Path(sys.argv[1]))
    except (OSError, ValueError, json.JSONDecodeError) as error:
        raise SystemExit(f"Could not review HAR: {error}")

Run it from your own terminal, giving it the path of a file you have permission to inspect:

python har_audit_local.py path/to/capture.har

For a two-entry synthetic HAR used to check the script, it produced:

Entries: 2. Review every URL and header value manually.
Entry 1: URL query, queryString, request sensitive-looking header name, request body, response body
This is an incomplete triage, not proof that the HAR is safe to share.

The synthetic sample deliberately contained a query parameter, a header named X-API-Key, a JSON request body and a JSON response body. The second entry had none of the script's flagged fields. The script was run against that local fixture with Python and compiled without errors; it was not evaluated against real customer HAR files or every browser export variant.

What this script cannot tell you

The script does not parse every possible body format, inspect encoded content, check arbitrary header values, or decide whether an internal URL is confidential. Its simple name check can miss a secret stored under an unexpected label. It examines the first 25 flagged entries in its displayed output, although it counts the others; the 25 MB input cap is a practical limit for this example, not a declaration that smaller HAR files are safe.

It also does not remove or mask anything in the input file. Python's JSON documentation advises caution when parsing untrusted JSON because of possible resource consumption. Use an appropriate controlled environment if the HAR came from an untrusted party; the input-size check is not a sandbox.

Use the output to prioritise a manual inspection of the actual content. Never attach the original HAR on the assumption that this script has cleaned it.

Decide what you can share without destroying the evidence

Review what support needs to diagnose. If a request URL or header contains a token, ask whether they can work from a redacted version, a test account, or just the relevant response status and timing. Editing away request bodies or entire entries can make a trace less useful, so coordinate the scope rather than removing fields at random and implying the resulting file is identical to what the browser recorded.

If you do create a redacted copy, keep the original securely in your own approved storage, label the copy as edited and check the edited file itself again. Search both obvious JSON fields and other text or encoded content. Do not use an arbitrary third-party “HAR cleaner” website unless your organisation has explicitly approved transferring that data there.

Some support workflows legitimately require a complete sensitive trace. For example, Microsoft's Azure DevOps support procedure documents how to enable export with sensitive data for their troubleshooting process, while warning that the file may contain authentication information. That is a specific support workflow, not a reason to turn on sensitive export for every help request.

If someone asks for an unredacted HAR, verify that they represent the service you are contacting, confirm which data is necessary, and use the provider's authenticated, access-controlled upload route. Avoid public GitHub issues, public paste sites and broad chat channels for files containing account activity. Follow your workplace's incident and retention rules if applicable.

If a trace containing an active credential has already been exposed to an unauthorised recipient, treat it as a possible credential disclosure. Use the service's supported way to revoke or rotate the affected key, token or session, and notify the responsible security or support team when required. Deleting the sent message alone does not establish that copies no longer exist.

The practical sharing rule

A good support trace shows the shortest sequence that reproduces the failure. Capture that sequence, use the browser's documented sanitised option when available, inspect the actual file and send only the necessary copy by a trusted route.

If you cannot tell whether the contents are appropriate to disclose, do not guess. Ask for a narrower diagnostic, a test-account reproduction or a secure review process before attaching it.

Sources and further reading

The following source pages and relevant sections were checked on 1 November 2026:

Share this post