Skip to content

How to Modify HTTPS Requests and Responses with JavaScript on iPhone

Write small JavaScript scripts to change URLs, headers, query parameters and JSON bodies of matching iPhone traffic, with logs and examples.

2 min readHTTPS Capture

Fixed rules break down once you need logic. You might need to add a signature header computed from the body, change a field only when another field has a certain value, or count requests across calls. HTTPS Capture runs JavaScript scripts on matching traffic, directly on the iPhone. It is similar to the scripting found in desktop tools like Proxyman or mitmproxy.

Create a script

  1. On the Capture tab, tap Rules → Scripts.
  2. Turn on Enable Scripts.
  3. Tap New Script to start from a template, use Examples to pick one of the built-in samples, or Import Script to load a .capture.js file.

The editor has syntax highlighting, line numbers and bracket completion. When you save, the script is checked for errors, and it applies to new requests right away.

The script format

Every script calls Capture.defineScript once:

Capture.defineScript({
  name: "Add debug header",
  version: "1.0.0",
  match: {
    urls: ["https://api.example.com/*"],
    methods: ["GET", "POST"]
  },

  onRequestHeaders(context, request) {
    request.headers.set("X-Debug", "1");
    request.queries.set("lang", "en");
    return request;
  }
});

There are five optional hooks:

HookWhen it runs
shouldMatch(request)Extra check; return false to skip this request
onRequestHeaders(context, request)Before the request is sent; change URL, method, headers or query
onRequest(context, request)After the full request body is available
onResponseHeaders(context, request, response)When response headers arrive
onResponse(context, request, response)After the full response body is available

Example: edit a JSON response

Capture.defineScript({
  name: "Unlock feature flag",
  version: "1.0.0",
  match: { urls: ["https://api.example.com/config*"] },

  onResponse(context, request, response) {
    const body = JSON.parse(response.body || "{}");
    body.features = body.features || {};
    body.features.newCheckout = true;
    response.body = JSON.stringify(body);
    return response;
  }
});

Useful APIs

  • request.url, method, host, port, path: read or change the destination
  • request.headers and request.queries: get, set, append, delete, or simple property access like request.headers["X-Debug"] = "1"
  • request.body / response.body as text, or bodyBytes for binary data
  • response.statusCode
  • context.state: share data between the hooks of the same request
  • context.shared: share data across requests while capture is running
  • env.get(key) / env.set(key, value): persistent values, such as a token you want to reuse
  • Capture.crypto.md5(), Capture.crypto.sha256(), Capture.base64.encode() / decode()
  • console.log() output appears under Runtime Logs

Return null from a request hook to block that request.

Safe by design

Scripts run in a sandbox. Network APIs (fetch, XMLHttpRequest, WebSocket) are disabled, and each hook has a strict time limit. If a script throws an error or runs too long, the traffic passes through unchanged and the error is logged. A bug in your script won’t take the network down. Only the first enabled script that matches handles a given request, and you can drag scripts to set their priority.

Let AI write the script

Tap AI Prompt to copy the complete scripting reference. Paste it into ChatGPT, Claude or another assistant together with what you want, and you will get a script that follows the API exactly.

For simple fixed changes, a rewrite rule is quicker. For one-off manual edits, use a breakpoint.

HTTPS Capture

Capture and decrypt HTTPS traffic on iPhone

App Store

Ready to try it?

HTTPS Capture · Capture and decrypt HTTPS traffic on iPhone

Free on the App Store