DevTools
Back to Blog
How to Redact HAR Files Safely (Keep Tests Shareable, Remove Secrets)

How to Redact HAR Files Safely (Keep Tests Shareable, Remove Secrets)

DevTools TeamDevTools Team

HAR captures are great raw material for regression tests because they reflect what actually hit your backend. They are also one of the easiest ways to accidentally leak credentials, session cookies, API keys, CSRF tokens, and user data into Slack, issues, or Git.

This guide covers a practical, developer-friendly way to redact HAR files safely so you can keep tests shareable (reviewable in pull requests, runnable in CI) without shipping secrets.

Why HAR files are uniquely dangerous

A HAR file is effectively a bundle of:

  • Full request URLs (including query strings)
  • Request headers (often including Authorization and Cookie)
  • Request bodies (login payloads, tokens, PII)
  • Response headers and bodies (tokens, user profiles, emails, IDs)

Unlike many API-client exports, HAR captures are “everything that happened”, not “what you intended to keep”. The HAR 1.2 spec makes it clear that entries can include full content payloads.

If your goal is “generate deterministic API tests that can live in Git”, your goal is not “commit the HAR”. Your goal is “extract the behavior, parameterize the secrets, drop the rest”.

A safe workflow in one sentence

Keep the raw HAR local, sanitize it automatically, generate YAML tests, commit only the YAML (plus non-secret fixtures), and inject secrets at runtime via CI or env.

Simple pipeline diagram showing: raw HAR file on a developer laptop flows into a sanitizer step, then into YAML API flows stored in Git, then executed by CI runners with secrets injected from the CI environment.

What to redact (and what to keep)

Redaction is easiest if you start from an explicit policy: an allowlist for what is safe, and a denylist for what is never safe.

High-risk fields you should treat as secrets by default

Location in HARTypical keysWhy it’s riskySafer replacement
Request headersAuthorization, Cookie, X-API-Key, X-Auth-TokenDirect credential materialReplace with ${ENV_VAR} or obtain via login step
Response headersSet-CookieSession fixation, replayDrop entirely in committed artifacts
Query stringtoken, key, code, signature, X-Amz-SignatureCredentials often passed in URLReplace with ${ENV_VAR} or re-generate in test
Request bodypassword, client_secret, refresh_tokenCredential material, PIIReplace with ${ENV_VAR} or fixture with dummy values
Response bodyaccess_token, id_token, user objectsTokens and PIIDrop body, or store sanitized fixture (if needed)

Data you usually should keep

Keep the minimum needed to reproduce and assert behavior:

  • Method, path, and stable query params
  • Stable headers (often Content-Type, Accept)
  • JSON bodies, but with secrets replaced
  • A small set of assertions that don’t depend on volatile values

Data you usually should drop for determinism

Dropping these makes CI runs reproducible:

  • Cookie, Set-Cookie
  • Content-Length (will change after redaction)
  • User-Agent, sec-ch-*, Origin, Referer (often irrelevant for API regression)
  • Tracing headers (x-request-id, traceparent) and timestamps

Redaction strategy: minimize, parameterize, then chain

There are three patterns that keep tests shareable:

1) Minimize captured scope

Even if you already have a HAR, you can aggressively reduce what you convert into tests:

  • Filter to a single domain or set of API hosts.
  • Drop static assets and third-party calls.
  • Keep only the requests that represent a workflow boundary (login, create resource, fetch resource, cleanup).

(If you need a safe capture process, DevTools has a separate guide on generating a HAR file in Chrome safely. This article focuses on what to do after you have one.)

2) Parameterize secrets into environment variables

When something must be provided externally (API keys, client secrets, long-lived tokens), replace the literal value with an env var placeholder.

Example pattern in YAML:

steps:
  - id: list_projects
    request:
      method: GET
      url: ${env.API_BASE_URL}/v1/projects
      headers:
        Authorization: Bearer ${env.API_TOKEN}
        Accept: application/json
    expect:
      status: 200

This keeps the flow reviewable in Git, and your CI can inject ${env.API_TOKEN} from its secret store.

3) Replace replayed sessions with request chaining

The most common HAR leak is “it worked because the browser had a session cookie”. Don’t commit that. Instead, make auth explicit:

  • A login step that returns a token
  • Capture the token
  • Use the captured token on subsequent requests

Example (illustrative YAML):

steps:
  - id: login
    request:
      method: POST
      url: ${env.API_BASE_URL}/auth/login
      headers:
        Content-Type: application/json
      body:
        username: ${env.TEST_USERNAME}
        password: ${env.TEST_PASSWORD}
    expect:
      status: 200
    capture:
      access_token: $.access_token

  - id: create_widget
    request:
      method: POST
      url: ${env.API_BASE_URL}/v1/widgets
      headers:
        Authorization: Bearer ${capture.access_token}
        Content-Type: application/json
      body:
        name: ci-${env.RUN_ID}
    expect:
      status: 201
    capture:
      widget_id: $.id

  - id: get_widget
    request:
      method: GET
      url: ${env.API_BASE_URL}/v1/widgets/${capture.widget_id}
      headers:
        Authorization: Bearer ${capture.access_token}
    expect:
      status: 200

The key point: the test is shareable because it’s no longer “replay this exact browser session”. It’s “execute an API workflow”.

A practical HAR redaction policy (that won’t break conversions)

Instead of chasing every possible secret pattern, start with a deterministic policy.

Header policy

  • Delete headers by name (case-insensitive) if they are known secret carriers.
  • Prefer allowlisting stable headers when possible.

Denylist candidates:

  • authorization
  • cookie
  • set-cookie
  • x-api-key
  • x-auth-token
  • proxy-authorization

Also delete volatility headers to reduce diff noise:

  • content-length
  • date
  • expires
  • if-none-match
  • if-modified-since
  • x-request-id
  • traceparent

Query string policy

  • If a parameter name matches common secret names (token, key, signature, password, code), redact.
  • If it is an OAuth authorization code or signed URL, you typically should not convert it directly into a committed test. Re-generate it via the auth flow.

Body policy

  • For JSON, traverse keys and redact by key name match.
  • For form-encoded bodies, redact values by key.
  • For GraphQL, redact variables payload fields (many teams accidentally commit user emails and auth headers here).

Response content policy

If your HAR was exported “with content”, responses can leak PII and tokens.

  • Default: drop response bodies from anything you plan to share.
  • Exception: keep small, sanitized fixtures only when assertions depend on specific response shapes.

Automate redaction (do not do it by hand)

Manual editing is how secrets slip through review. Automate redaction so it is:

  • Repeatable
  • Reviewable (diffable)
  • Enforceable (hooks and CI checks)

Minimal sanitizer approach

A sanitizer can be simple:

  • Parse HAR JSON
  • For each entry:
    • Redact header values based on header name
    • Redact query params by key name
    • Redact request body fields by key name (when JSON)
    • Optionally delete response content

If you already use secret scanners, run them on the sanitized output as a backstop.

Good options:

  • Gitleaks (fast, easy to run in CI)
  • TruffleHog (strong detectors, good for repo scanning)

Keep Git clean: what to commit vs what to ignore

A stable team convention:

  • Do not commit raw HAR files.
  • Commit generated YAML flows.
  • Commit non-secret fixtures (sanitized JSON responses, if needed).

A basic .gitignore stance (adapt to your repo):

# Raw captures
*.har
captures/

# Local env files
.env
*.local.yml

Add a pre-commit guardrail (YAML example)

If your team uses pre-commit, you can block accidental HAR commits and run scanners locally.

repos:
  - repo: local
    hooks:
      - id: block-har
        name: Block committing HAR files
        entry: bash -c 'git diff --cached --name-only | grep -E "\\.har$" && echo "Do not commit HAR files" && exit 1 || exit 0'
        language: system

  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.24.0
    hooks:
      - id: gitleaks

This doesn’t replace careful engineering, but it makes failures loud and early.

How this differs from Postman, Newman, and Bruno

HAR-based workflows and “API client collections” solve different problems, but teams often mix them.

Postman and Newman

  • Postman collections and environments are exportable, but secrets often end up in environment JSON, local values, or synced workspaces.
  • Newman runs collections in CI, but the data model is still “collection + environment + scripts”. It works, but review diffs can be noisy, and secret handling becomes a process issue.

Bruno

  • Bruno is closer to “tests as files”, and it avoids some cloud coupling.
  • However, you still need conventions to keep secrets out of request files and to make request chaining deterministic.

YAML-first flows (and why it matters for redaction)

With YAML-first API testing, you can make redaction and shareability structural:

  • The committed artifact is human-readable YAML.
  • Secrets become obvious placeholders (${env.*}), not opaque values buried in exported JSON.
  • Request chaining is explicit, so you don’t need to preserve browser cookies from the HAR.

If you’re converting captured traffic into Git-native tests, the important transition is: from “captured session replay” to “declarative workflow with explicit inputs”.

For a concrete “HAR to YAML to CI” path, see HAR to YAML: Generate API Regression Tests for CI.

Common redaction pitfalls (and how to avoid them)

Redacting a value but leaving a valid session cookie shape

If you keep Cookie: session=REDACTED, some servers treat it as an invalid session and return a different code path than an unauthenticated request.

Preferred fixes:

  • Remove the Cookie header entirely.
  • Replace cookie-based auth with a login step and token capture.

Keeping Content-Length

After you redact bodies, Content-Length is wrong. Many servers ignore it for typical clients, but some stacks and proxies do not.

Fix: drop Content-Length from captured headers.

Redacting CSRF tokens without replacing the flow

If your web app requires CSRF tokens, they are typically generated per session.

Fix: model the CSRF acquisition step (fetch page or preflight endpoint), capture the token, then use it. Do not hardcode it from the HAR.

Leaving secrets in response content

Teams often redact only request headers and miss:

  • access_token in JSON responses
  • password reset links
  • email addresses and IDs

Fix: drop response bodies by default and add back only sanitized fixtures when needed.

A “shareable tests” checklist for teams

Before you upload or PR anything derived from har files:

  • No raw .har in Git.
  • No Authorization, Cookie, Set-Cookie in committed artifacts.
  • No tokens, emails, or reset links in response bodies.
  • Secrets are only referenced via env placeholders.
  • Auth is explicit (request chaining), not “replay browser state”.
  • CI injects secrets, and logs do not print sensitive headers or bodies.

If you want a Git workflow framing for this, the PR checklist approach in GitHub Flow Explained for API Testing Teams pairs well with “tests must be reviewable and safe to share”.

Frequently Asked Questions

Should I ever commit a HAR file to a repo? Generally no. Treat raw HAR files like packet captures: useful locally, unsafe as a shared artifact. Commit the sanitized YAML flow instead.

Is replacing secrets with REDACTED enough? Not reliably. You also need to remove session-dependent headers (cookies) and rework auth into explicit request chaining, otherwise tests won’t be deterministic.

What’s the safest way to share a HAR with a vendor or another team? Share only a sanitized HAR with response bodies removed, and run a secret scanner on it first. Better: share a YAML flow that references env vars instead of containing credentials.

How do I handle OAuth flows captured in a HAR? Don’t commit authorization codes or signed redirect URLs. Model the token exchange explicitly (or inject a client credential via env), then capture the access token during the test run.

Why does my test fail after redaction even though the HAR worked? The HAR likely depended on browser state (cookies, CSRF tokens, cached auth). Fix it by deleting those headers and making the state transitions explicit via chaining and captures.

Turn a HAR into a reviewable YAML test (without leaking secrets)

If your end goal is Git-native API regression tests, the clean path is: capture traffic, convert it into a YAML workflow, replace secrets with environment variables, and make auth and request chaining explicit.

DevTools is built around that workflow: it converts HAR captures into human-readable YAML flows that are easy to review in pull requests and run locally or in CI. Start from the safe capture guide (Generate a HAR file in Chrome) and then follow the end-to-end example (HAR to YAML for CI).