Body Rewrite

Chute can search and replace content in HTTP request and response bodies using regular expressions or JSONPath expressions. This requires MitM decryption for HTTPS traffic.

Notice: A plain HTTP request is processed only when it reaches Chute through its HTTP proxy; plain HTTP that arrives through the TUN interface is forwarded untouched. Chute Android sends all traffic through TUN unless System HTTP Proxy is turned on in Settings, which hands apps Chute's HTTP proxy (Android 10 and later; off by default).

Surge's http-request-jq and http-response-jq programs are supported as well — see Surge Syntax.

Body rewrite rules are defined in the [Body Rewrite] section. For each direction (request / response), only the first matching rule is applied to a message. When an http-request or http-response script that takes the body matches the same message, the rule is applied first and the script sees the rewritten body; an http-request-before-send script runs after both.

[Body Rewrite]
^https://api\.example\.com/response.* response regex "old-text" "new-text"
^https://api\.example\.com/request.* request regex "sensitive" "[redacted]"
^https://api\.example\.com/data.* jsonpath-response jsonpath $.ads null

Rule Format

Each rule follows this general format:

<URL regex> [direction] <mode> <pattern> <replacement>

Notice: The URL regular expression is matched anywhere in the request's full URL, and in its path alone, as in URL Rewrite: ^https://example\.com already covers every path and query string under that host, so a trailing .* is unnecessary, and ^/api matches every request whose path starts with /api. The full URL of a decrypted request starts with https://, so a ^http:// pattern never matches one. The pattern keeps its case, so \S, \D, \W and \B mean what they say; the match itself ignores case.

A # or // at the start of the line or after a space begins a comment that runs to the end of the line, unless it is inside double quotes; ; never does. See Comment.

Surge Syntax

Surge's own line shape is accepted as well: the direction comes first, and the regex keyword is left out.

[Body Rewrite]
http-response ^https://api\.example\.com/feed "\"ads\":\s*\[.*?\]" "\"ads\":[]"
http-request ^https://api\.example\.com/submit "sensitive" "[redacted]"

A Surge line may carry several pattern/replacement pairs; they are applied left to right, each to the result of the one before. http-request-jq and http-response-jq take a jq program instead of a pattern and a replacement: <type> <URL pattern> <jq program>, with the program usually quoted because it contains spaces. Outside the quotes, a // or # that follows a space starts a comment, which ends the program there; inside them // is jq's alternative operator, so quote a program that uses it. It runs over the body as JSON. A body that is not JSON, a program that raises, and a program that produces no output all leave the body exactly as it was; an invalid program is reported and that one rule is skipped, without making the rest of the profile fail. A program cannot read files or the environment: import and include resolve nothing, and $ENV and env are empty.

Notice: Chute Android runs jq programs on jackson-jq. Its output is capped at 4096 results or 4 MB — a program that produces more leaves the body as it was — and it lacks some jq 1.7 builtins, among them the date functions other than now, todateiso8601 and fromdateiso8601 (strftime, strptime, mktime, gmtime, todate and the like), @base32 and @base32d, abs, toarray, trim, ltrim and rtrim, IN, INDEX and JOIN, tostream and fromstream. A program that calls one of them raises when it runs, which leaves the body as it was.

Direction

Keyword Description
response Apply to response body (default if omitted)
request Apply to request body

Modes

Mode Description
regex Regular expression search-and-replace
jsonpath-response / jsonpath-request / body-jsonpath-response / body-jsonpath-request JSONPath-based modification

Regex Mode

Performs standard regex find-and-replace on the decoded body text. Uses NSRegularExpression (ICU) with case-insensitive matching. The replacement supports capture group references ($1, $2, etc.).

<URL regex> [response|request] regex <pattern> <replacement>

Example — remove ads from JSON response:

[Body Rewrite]
^https://api\.example\.com/feed.* response regex "\"ads\":\s*\[.*?\]" "\"ads\":[]"

Example — sanitize request body:

[Body Rewrite]
^https://api\.example\.com/submit.* request regex "\"password\":\s*\".*?\"" "\"password\":\"[FILTERED]\""

Example — use capture groups to reformat data:

[Body Rewrite]
// Swap "last, first" to "first last"
^https://api\.example\.com/users.* response regex "\"name\":\s*\"(\w+),\s*(\w+)\"" "\"name\":\"$2 $1\""

Example — rewrite embedded URLs in response body:

[Body Rewrite]
^https://api\.example\.com.* response regex "https://old-cdn\.example\.com" "https://new-cdn.example.com"

Tokens containing spaces must be quoted with double quotes:

[Body Rewrite]
^https://example\.com.* response regex "old value with spaces" "new value"

To include a literal double quote inside a quoted token, escape it with backslash: \".


JSONPath Mode

Modifies JSON bodies using JSONPath expressions. Supports reading, setting, and deleting values at specific paths.

<URL regex> jsonpath-response|jsonpath-request jsonpath <jsonpath-expression> [value]

Supported JSONPath Syntax

Expression Description
$.key Access object property
$.key.subkey Access nested properties
$[0] Access array element by index
$.key[0].subkey Mixed object and array access
$.items[*].name Wildcard: all items in array
$.*.value Wildcard: all properties

.* takes every member of an object and every element of an array, so $.items.*.name reaches the name of each item. As the last step on an array it changes nothing; to replace the elements themselves, use [*].

Value Types

Value Result
string Set to string value — anything that is not one of the forms below, so example.com, 1.0.0-beta and 12abc stay strings
42 Set to integer — a token that is a JSON number in full, with no fraction or exponent
3.14 Set to float — a JSON number with a fraction or an exponent, such as 1e3, or an integer too large for 64 bits
true Set to boolean true
false Set to boolean false
[…] or {…} Unquoted, parsed as JSON and set as that array or object; it is the last field, so the rest of the line is taken as written and may contain spaces. Quoted, or not valid JSON, it stays a string.
null, nil or omitted Delete the path

Notice: Quoting a value does not force string type — quotes are stripped during tokenization and the type is inferred from the remaining content, so "42" becomes the number 42, "true" becomes boolean true and "null" deletes the path; the quotes matter only for […] and {…}, which stay strings when quoted. The keywords are matched exactly, so True and NULL are strings. A number counts only when the whole token is one, written as JSON writes it: +1, .5, 1. and 007 stay strings, and so does a number too large for a float, such as 1e400. There is no spelling that sets a string such as "42" or "true" — use a regex rule for it instead.

Example — set a JSON field:

[Body Rewrite]
^https://api\.example\.com/profile.* jsonpath-response jsonpath $.user.name "Anonymous"

Example — delete a JSON field:

[Body Rewrite]
^https://api\.example\.com/data.* jsonpath-response jsonpath $.tracking null

Example — wildcard modification:

[Body Rewrite]
^https://api\.example\.com/list.* jsonpath-response jsonpath $.items[*].hidden true

Practical Examples

Strip Tracking Parameters from JSON Responses

Remove the trackingId field from all API responses. Since only the first matching rule per direction is applied, use one rule per URL pattern:

[Body Rewrite]
^https://api\.example\.com/.* jsonpath-response jsonpath $.trackingId null

Inject a script tag into HTML responses

Append a custom <script> tag before </body> in all HTML pages:

[Body Rewrite]
^https://www\.example\.com/.* response regex "</body>" "<script>console.log('injected')</script></body>"

Redact sensitive fields in request logs

Replace API keys and tokens in outgoing request bodies before they reach the server. Since only the first matching rule per direction is applied, combine both fields into a single rule:

[Body Rewrite]
^https://api\.example\.com/.* request regex "\"(apiKey|token)\":\s*\"[^\"]+\"" "\"$1\":\"[REDACTED]\""

Normalize date formats in responses

Replace ISO dates with a shorter format:

[Body Rewrite]
^https://api\.example\.com/.* response regex "(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z" "$1/$2/$3 $4:$5"

Disable feature flags in app config

Force all feature flags to false in a configuration endpoint:

[Body Rewrite]
^https://api\.example\.com/config.* jsonpath-response jsonpath $.features[*].enabled false

Rewrite CDN URLs in cached responses

Replace all references to an old CDN with a new one:

[Body Rewrite]
^https://www\.example\.com/.* response regex "https://old-cdn\.example\.com" "https://new-cdn.example.com"

Processing Pipeline

Body rewrite automatically handles:

  1. Content-Encoding: Supports gzip and deflate. Skips unsupported encodings.
  2. Transfer-Encoding: De-chunks chunked transfer encoding before processing.
  3. Decoding: Decompresses bodies before applying rewrite rules.
  4. Re-encoding: Re-compresses bodies and updates Content-Length. Removes Transfer-Encoding header.
  5. Accept-Encoding: When a response rule matches a request's URL, the request's Accept-Encoding header is rewritten to gzip, deflate, identity so that the response stays in a decodable encoding.

Max body size for rewrite processing is 128KB on HTTP/1.x (plain HTTP and decrypted HTTP/1.1); larger bodies are passed through without modification. A decrypted HTTP/2 message is buffered whole and rewritten whatever its size.

On HTTP/1.x a response body is rewritten once all of it has arrived. When the server closes the connection first, a body with neither Content-Length nor chunked encoding is complete — the close is its end — and is rewritten as usual. A Content-Length or chunked body that the close cut short goes to the client exactly as it arrived, not rewritten and with its Content-Length untouched, and the connection is then closed, so the client can tell that the response is incomplete.


Notes

  • For HTTPS traffic, MitM decryption must be enabled for the matching hostname.
  • Regex matching is case-insensitive. The replacement template supports ICU capture group references: $0 (full match), $1 (first group), $2 (second group), etc.
  • A URL pattern or a body pattern that is not a valid regular expression makes a regex or JSONPath line a configuration error, and the rule is not loaded; a jq line is skipped with a warning instead. In the pairs after the first, an invalid pattern drops only that pair, with a warning in the log.
  • JSONPath mode only applies if the body is valid JSON.
  • Body rewrite rules are applied to the decoded (UTF-8) body text.
  • Only the first matching rule per direction (request / response) is applied to a message. Define one combined rule if you need multiple edits.
  • Deleting a non-existent JSONPath leaves the body unchanged. Setting a value creates the key when its parent object exists; if an intermediate path is missing, nothing happens.
S. Smart Rabbit LLC © All Rights Reserved            updated 2026-09-25 00:02:29

results matching ""

    No results matching ""