# Your coding agent is guessing your mobile app's API. Give it a redacted HAR instead.

> Source: <https://dev.to/minpin_proxy/your-coding-agent-is-guessing-your-mobile-apps-api-give-it-a-redacted-har-instead-1095>
> Published: 2026-11-15 13:09:10+00:00

You ask your coding agent why the orders screen is empty. It reads the client code, reads the model, and then writes a confident fix for a response shape it has never seen. The real response was a `200` with `{"items":[],"error":"quota"}` in the body. Nothing on screen said so, and nothing in the code could.

For web apps the agent can sometimes look at the browser. For a mobile app it can't see anything unless you give it the traffic. The steps below work with any HTTPS debugging proxy (mitmproxy, or whichever one you already use). Examples assume it listens on `127.0.0.1:8080` and that you've exported its CA certificate.

**iOS Simulator.** The Simulator uses the Mac's network settings, so the Mac's system proxy applies. Trust the CA once per simulator:

```
xcrun simctl keychain booted add-root-cert ~/proxy-ca.pem
```

Then restart the app.

**Android emulator.** Start it with the proxy:

```
emulator -avd Pixel_8 -http-proxy http://127.0.0.1:8080
```

`127.0.0.1` here is your Mac, because the emulator process applies the flag on the host side. Install the CA as a user certificate. Since Android 7, apps ignore user CAs unless you opt in for debug builds:

``` php
<!-- res/xml/network_security_config.xml -->
<network-security-config>
  <debug-overrides>
    <trust-anchors>
      <certificates src="user" />
    </trust-anchors>
  </debug-overrides>
</network-security-config>
```

Reference it from the manifest with `android:networkSecurityConfig="@xml/network_security_config"`. `debug-overrides` only applies to debuggable builds, so release builds stay strict.

**Flutter.** Dart's `HttpClient` ignores the system proxy on every platform. In debug builds, set an `HttpOverrides` whose `findProxy` returns `PROXY <host>:8080`.

**A real iPhone.** Wi-Fi settings → your network → Configure Proxy → Manual, with your Mac's LAN IP and port. Install the CA profile, then switch it on under Settings → General → About → Certificate Trust Settings. Installing the profile alone is not enough.

Clear the session, do the one thing that's broken, and export just that as a HAR. A short, focused capture beats an hour of background noise. The agent reads every byte you give it.

A HAR carries everything: bearer tokens, cookies, API keys in query strings. Don't paste that into a model. This jq filter keeps one API host, masks anything that looks like a credential, and truncates very large bodies:

```
# redact.jq
def secret: ascii_downcase | test("authorization|cookie|token|secret|api[-_]?key|session|signature|password");
.log.entries |= map(select(.request.url | startswith("https://api.example.com/")))
| .log.entries[] |= (
    (.request.headers, .response.headers) |= map(if (.name | secret) then .value = "REDACTED" else . end)
  | .request.queryString |= map(if (.name | secret) then .value = "REDACTED" else . end)
  | .request.url |= gsub("(?<k>[?&][^=&]*(token|key|secret|sig|session)[^=&]*)=[^&]*"; "\(.k)=REDACTED"; "i")
  | .request.cookies = [] | .response.cookies = []
  | .response.content.text |= (if . == null then . else .[:20000] end)
  )
jq -f redact.jq capture.har > capture.redacted.har
grep -oE 'eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+' capture.redacted.har   # leftover JWTs?
```

The filter only looks at names. Tokens inside JSON bodies (a login response, a refresh call) still get through, which is what the `grep` is for. Read the file before you hand it over. A sanitized HAR still needs a look.

Put the file in the repo (and in `.gitignore`), then ask something specific:

`capture.redacted.har` has the requests from opening the Orders screen. Which request feeds the list, what did it return, and why does the UI show nothing? Point to the code path.

What tends to come back:

`200` responses that carry an error in the body, which the client treats as success.`orderId` vs `order_id`, a number sent as a string), so the whole decode fails silently.
This article was created with the help of AI.
