# Trace Value

> Follow an ID, token or email through captured traffic, from the response it came from to every request that sent it, with the exact header, parameter or key.

Source: https://docs.subcloak.com/cloak-proxy/inspect/trace-value/

Added in Cloak Proxy 0.2.1.

Trace Value follows one value, such as an order ID, an access token or an email address, through everything Cloak Proxy captured. It shows the response the value first came from, every endpoint that sent it afterwards and exactly where (the path, a query parameter, a header, a cookie or a JSON key), and the responses that returned it again. Use it to understand how an app chains its API calls, to see which calls depend on a login token, or to check whether an ID your server issued ends up somewhere it shouldn't, such as an analytics service.

> **Looking for OpenTelemetry traces?:**
> Trace Value follows a value through your captured requests. To see OpenTelemetry trace IDs and open them in Jaeger, Honeycomb or Datadog, see [Distributed tracing](https://docs.subcloak.com/cloak-proxy/inspect/distributed-tracing/).

## Trace a value

1. Open Trace Value in one of these ways:

   - Choose **Tools › Trace Value…** (<kbd>⇧</kbd> <kbd>⌘</kbd> <kbd>T</kbd>). If the quick filter holds text, Trace Value traces it; otherwise the window opens empty.
   - Type the value in the [quick filter](https://docs.subcloak.com/cloak-proxy/inspect/filtering/) and click **Trace** next to the result count. The button appears once the filter text is at least 3 characters.
   - In the [JSON tree](https://docs.subcloak.com/cloak-proxy/inspect/body-viewers/), right-click a value and choose **Trace “_value_”**.
   - In a **Header**, **Query**, **Form**, **Cookies** or **Set-Cookie** table in the [inspector](https://docs.subcloak.com/cloak-proxy/inspect/inspector/), right-click one row and choose **Trace Value**.
   - Right-click a request in the [traffic list](https://docs.subcloak.com/cloak-proxy/inspect/traffic-list/) and choose **Trace Value…**, or **Trace “_text_”…** when the quick filter holds text.

2. If the field is empty, type the value and press <kbd>Return</kbd> or click **Trace**.

   The value must be at least 3 characters. Spaces at either end are ignored.

3. Read the summary at the top, then follow the flow map from left to right.

4. Click a card in the flow map or a row under **Every occurrence** to select those requests in the traffic list.

Each time you trace from somewhere else in the app, the same Trace Value window shows the new value.

*[Screenshot: The Trace Value window for fc68188e: it appears in 7 requests to 6 endpoints, first in the response to POST api.example.com/v1/orders at body $.data.order.id, then sent by five endpoints in the path, a query parameter, a header and JSON keys, with two responses that returned it again and a list of every occurrence below. An order ID created by one call, then sent to five others, including an events endpoint.]*

## Read a trace

### The summary

The first line says how many requests contained the value and how many endpoints they went to, for example **fc68188e appears in 7 requests to 6 endpoints**. The second line names where it came from:

| Origin | What it means |
|---|---|
| **It first appeared in the response to** _endpoint_ **at** _time_ | A response delivered the value before any request sent it: the server issued it. The line ends with the place in that response and how many endpoints sent it afterwards. |
| **It was first sent by** _endpoint_ **at** _time_ | A request sent the value before any captured response contained it. The app made it up, or got it from traffic Cloak Proxy didn't capture: another device, a pinned connection, or a session before this one. |

Cloak Proxy compares when each request started with when each response finished, so a value returned by a response counts as its origin only if no request sent it earlier.

When more than 5,000 requests contain the value, an orange note says **Only the first 5,000 matches are traced.**

### The flow map

The flow map has up to three columns, with arrows from where the value came from to where it went:

| Column | Shows |
|---|---|
| **First appeared** | The response (or request) the value came from. It's outlined in the accent color. |
| **Then sent by** | Every endpoint whose requests sent the value afterwards, in the order each was first used. **No later request sent it.** when there are none. |
| **Returned again by** | Endpoints whose responses contained the value again after it first appeared. Only shown when there are some. A response is linked to its own endpoint's card in **Then sent by** when that endpoint also sent the value, otherwise to the origin. |

Each card shows:

- The method and whether the card is about the **request** or the **response**.
- **×N** when several requests to the endpoint carried the value.
- The host and path. A path segment that contains the value is shown as `{value}`, and other IDs as placeholders, so requests to the same endpoint group together: `api.example.com/v1/orders/{value}`.
- Where the value was, as chips. A card shows up to 6; hover **+N more** to see the rest.

Click a card to select its requests in the traffic list.

### Where a value can be

| Chip | The value is in |
|---|---|
| `path` | The URL path |
| `query order_id` | A query parameter's value, or its name |
| `header X-Order-Id` | A request or response header (not cookies) |
| `cookie session` | A cookie in the request's `Cookie` header |
| `Set-Cookie session` | A cookie the response set |
| `body $.data.order.id` | A JSON body, at that path. Array positions are shown as `[*]`, so the same key in every item of a list is one place: `body $.items[*].order_id`. A key that contains the value counts too. |
| `body order_id` | A form field in an `application/x-www-form-urlencoded` body |
| `body` | Any other body, such as plain text or XML |

A body lists at most 8 places. Bodies compressed with gzip, deflate or Brotli are decompressed before they're searched.

### Placeholders in paths

To group requests by endpoint, Trace Value replaces IDs in paths with placeholders:

| Segment | Placeholder | Example |
|---|---|---|
| Contains the traced value | `{value}` | `/v1/orders/fc68188e` → `/v1/orders/{value}` |
| A number, a UUID, or 16 or more hexadecimal characters, after a plain word | `{wordId}`, named from the singular of the word before it | `/v1/users/42/last-order` → `/v1/users/{userId}/last-order` |
| The same, after anything else | `{id}` | `/v21.0/1234567890` → `/v21.0/{id}` |

The same placeholders are used when you [export OpenAPI](https://docs.subcloak.com/cloak-proxy/sessions/export/).

### Every occurrence

Under the flow map, **Every occurrence** lists each request that contained the value, oldest first:

| Column | Shows |
|---|---|
| Time | When the request started |
| **#** | The request's number in the traffic list |
| Role | **First appeared** or **First sent** for the origin, then **Sent**, **Returned**, or **Sent, returned** when both the request and its response had it |
| Request | Method, host and path |
| Where | Every place the value was, in the request and the response |

Click a row to select that request in the traffic list.

**Show All in Traffic List** sets the [quick filter](https://docs.subcloak.com/cloak-proxy/inspect/filtering/#search-every-request-and-response) to **All**, **Contains** and the value, and selects **All Traffic** in the sidebar, so the list shows every request that contains it.

## Controls

| Control | What it does |
|---|---|
| **A value to trace, e.g. an ID, token or email** | The value. Press <kbd>Return</kbd> to trace it. |
| **Trace** | Traces the value. Dimmed until the value is at least 3 characters. |
| **Make Replayable Flow** | Opens the [Make Replayable Flow](https://docs.subcloak.com/cloak-proxy/api-client/run/replayable-flows/) sheet with every request in the trace. Only when the trace found something. |
| **Copy Report** | Copies the trace as Markdown. Reads **Copied** until you change the value. Only when the trace found something. |

When nothing contains the value, the window says **_value_ isn't in any captured request**. Check the value, or capture the traffic that uses it first.

## How values are matched

- **Upper and lower case don't matter**, so `FC68188E` finds `fc68188e`.
- **Partial matches count.** Tracing `fc68` also finds `fc68188e`. Trace the whole value to avoid unrelated matches.
- **Everything except encrypted tunnels is searched**: URLs, every request and response header, cookies, and request and response bodies after decompression. Requests to hosts that aren't decrypted show up as tunnels and can't be traced into.
- **The trace runs once.** It uses the requests captured when you clicked **Trace**. Click **Trace** again to include newer ones.

## Copy the report

**Copy Report** puts a Markdown summary on the clipboard, ready for a bug report, a pull request or a security finding:

```md title="Copied report (shortened)"
## Value trace: `fc68188e`

Appears in 7 requests to 6 endpoints.
First appeared in the response to `POST api.example.com/v1/orders` (body $.data.order.id).

### Sent by

- `GET api.example.com/v1/orders/{value}` ×2: path
- `POST pay.example.com/v2/charge` ×1: query order_id

### Every occurrence

| Time | # | Request | Where |
|---|---|---|---|
| 1:49:03 AM | 40 | `POST api.example.com/v1/orders` | body $.data.order.id |
| 1:49:04 AM | 41 | `GET api.example.com/v1/orders/fc68188e` | path, body $.id |
```

The report has the summary, a **Sent by** list and a **Returned again by** list (when there are any), and a table of every occurrence.

> **Traces contain real values:**
> A report includes the value you traced and the full paths of the requests that carried it. If you traced a token, a session cookie or someone's email address, the report contains it. Trace and share values from your own test accounts, and remove secrets before posting a report anywhere.

## What to use it for

| Question | What to look at |
|---|---|
| Which calls need the login token? | Trace the token. **Then sent by** lists every endpoint that sent it, and in which header. |
| Where did this ID come from? | The origin. If it's **First sent**, the app created it, or it came from traffic you didn't capture. |
| Does an ID from our backend reach a third party? | Look for hosts that aren't yours under **Then sent by**. [Privacy Map](https://docs.subcloak.com/cloak-proxy/insights/privacy-map/) does this for every value at once. |
| Can I replay this sequence of calls? | Click **Make Replayable Flow**. It reads each ID from the fresh response when the flow runs. |
| Does the server accept another user's ID? | Trace your own ID to find every endpoint that takes one, then test them with [Edit and Repeat](https://docs.subcloak.com/cloak-proxy/tools/repeat-and-compose/) on your own test accounts. See [Pentest your own app](https://docs.subcloak.com/cloak-proxy/guides/pentest-your-own-app/). |

## Trace from an AI assistant

The [MCP server](https://docs.subcloak.com/cloak-proxy/automation/mcp-server/) has a read-only `trace_value` tool that takes a `value` of at least 3 characters. It returns the origin, the endpoints that sent and returned the value with where, and up to 200 occurrences, tracing at most 1,000 matching requests. The `search_requests` tool finds which requests contain a value without tracing it. See the [MCP tools reference](https://docs.subcloak.com/cloak-proxy/automation/mcp-tools-reference/#trace_value).

## Related

  - [Filtering](https://docs.subcloak.com/cloak-proxy/inspect/filtering/#search-every-request-and-response): Search every header and decoded body for a value with the quick filter.
  - [Replayable flows](https://docs.subcloak.com/cloak-proxy/api-client/run/replayable-flows/): Turn the requests in a trace into a flow that chains IDs and tokens.
  - [Privacy Map](https://docs.subcloak.com/cloak-proxy/insights/privacy-map/): See which outside companies receive your users' data and IDs.
  - [Body viewers](https://docs.subcloak.com/cloak-proxy/inspect/body-viewers/): The JSON tree, JSONPath and jq, where you can start a trace.
