# Doctor

> Find out why an app's or device's requests are missing or failing in Cloak Proxy, with the evidence and a one-click fix, plus a log of every connection.

Source: https://docs.subcloak.com/cloak-proxy/capture/doctor/

Added in Cloak Proxy 0.3.0.

The Doctor answers "why isn't my traffic showing?" It checks the macOS proxy, the certificate, your VPN, the app's own switches and every recent connection, then explains per app or device what is stopping its requests from showing or making them fail. Each problem comes with the evidence (hosts, counts, times) and one button that fixes it.

*[Screenshot: The Doctor window: FlutterNotes skips the proxy and Maps Pro uses HTTP/3, each with a Capture all its traffic button, ShopApp pins certificates for api.payments.example and auth.payments.example with a Stop decrypting these hosts button, Terminal's requests to staging.example fail, and a note that ExampleVPN is connected, followed by the list of checks that passed. Problems grouped by app, each with its evidence and a fix.]*

## Open the Doctor

| Where | What it shows |
|---|---|
| **Tools › Doctor…** | Everything, or the app selected in the sidebar |
| The stethoscope in the bottom bar | Everything. A red number next to it counts the problems found |
| Right-click an app in the sidebar › **Why isn't** app **showing traffic?** | That app |
| Right-click a device in the sidebar › **Why isn't this device showing traffic?** | That device |
| Right-click an app under **Not using the proxy** | That app |
| **Why?** next to a failed request's error in the inspector | The app that sent it |

Cloak Proxy runs the checks every 20 seconds in the background, so the count in the bottom bar stays current. The window checks again when it opens. Click the arrow button to check now.

At the top of the window, choose **Everything** or one app or device. Diagnosing one app also tells you when nothing is wrong: **App's traffic is showing**, with how many requests it sent and when the last one was, or **Cloak Proxy hasn't seen** the app **connect**.

## Read a finding

Findings are grouped under the app, the device, or **This Mac**.

| Part | Meaning |
|---|---|
| Red octagon | A problem: it stops traffic from showing or makes it fail. These are what the bottom bar counts. |
| Orange triangle | A warning: something you probably turned on yourself, such as paused recording or a filter. |
| Gray circle | A note, for example that a VPN is connected but traffic still arrives. |
| Gray chips | The hosts involved. Click **more** to see them all. |
| The last line | The evidence: how many connections or requests, the TLS alert, addresses, and when it last happened. |
| The button | The fix. **Learn more** opens the matching section of this page. |

Below the findings, **Checked** lists what was checked and is fine, for example "The macOS proxy points at Cloak Proxy (127.0.0.1:9090)." or, from 0.5.0, "The network extension captures curl." (added in Cloak Proxy 0.5.0) When nothing is wrong, the window says **Nothing is blocking traffic**.

## What the Doctor checks

| Finding | How it's detected | Fix button |
|---|---|---|
| **Cloak Proxy isn't listening** | The proxy couldn't open its port. | **Change the port** (Settings › Network) |
| **The macOS proxy is off** | macOS sends HTTP and HTTPS nowhere. A warning when you turned it off, a problem (**Something turned the macOS proxy off**) when Cloak Proxy had turned it on. | **Turn on macOS proxy** |
| **The macOS proxy points at** host:port | Another proxy is set. If an app on this Mac listens on that port, the Doctor names it. | **Point it at Cloak Proxy** |
| **A proxy auto-config file decides where traffic goes** | A PAC file is set instead of a fixed proxy. | **Point it at Cloak Proxy** |
| VPN **overrides the macOS proxy** | A VPN is connected or carries the default route, and the macOS proxy no longer points at Cloak Proxy. See [VPNs](#vpns). | **Set the proxy again** |
| **Recording is paused** | Requests go through but aren't added to the list. From 0.4.2, traffic passes through untouched by default (no decryption, no rules), and the evidence counts the connections that did; with **Keep intercepting, just don't record** it says requests are still decrypted with your rules. | **Resume recording** |
| **The filter hides every request** | Requests are captured, but the filter, a content chip or the sidebar selection hides all of them. When you diagnose one app: **The filter hides** N **of** app**'s requests**. | **Clear filters** |
| App **is muted** | Its requests went through Cloak Proxy recently and weren't recorded. | **Unmute** |
| **The Allow List skips** N **requests** | Requests that matched no [Allow List](https://docs.subcloak.com/cloak-proxy/tools/allow-list/) rule, with their hosts. | **Turn off the Allow List** |
| **The Cloak Proxy certificate isn't trusted on this Mac** | The root certificate isn't trusted in the login keychain. A problem when anything is set to be decrypted or apps refused the certificate. | **Trust the certificate** |
| App **skips the proxy** | The app has direct connections to the internet (the same check as **Not using the proxy** in the sidebar). | **Capture its domains**. From 0.5.0, with the Cloak Proxy download: **Capture all its traffic** ([App Capture](https://docs.subcloak.com/cloak-proxy/capture/capture-apps-that-ignore-the-proxy/)) (added in Cloak Proxy 0.5.0) |
| App **still skips the proxy for some servers** | A captured app also connects directly to servers outside its captured domains. | **Add its domains** |
| App **skips the proxy, and app capture is off** (added in Cloak Proxy 0.5.0) | The app is picked in [App Capture](https://docs.subcloak.com/cloak-proxy/capture/capture-apps-that-ignore-the-proxy/), but the extension isn't capturing, so its connections still go straight out. | **Turn on app capture** |
| **The network extension is waiting for your approval in System Settings** (or **App capture is off**, **App capture stopped**) (added in Cloak Proxy 0.5.0) | App Capture is wanted with apps picked, but macOS hasn't allowed the extension yet, Cloak Proxy isn't in Applications, or the extension stopped. Under **This Mac**. | **Open System Settings** or **Open app capture** |
| App **uses HTTP/3, which no proxy can see** | The app holds QUIC sockets. See [HTTP/3](#http3). | **Capture its domains**. From 0.5.0, with the Cloak Proxy download: **Capture all its traffic** (App Capture blocks its QUIC so it falls back to TCP) (added in Cloak Proxy 0.5.0) |
| App **pins certificates for** N **hosts** | The app refuses Cloak Proxy's certificate for some hosts while it's trusted. See [Certificate pinning](#certificate-pinning). | **Stop decrypting these hosts** |
| Host **answers with a bot challenge** (or N **sites**) (added in Cloak Proxy 0.4.2) | A decrypted request got Cloudflare's challenge: a 403 or 503 with `cf-mitigated: challenge`, or `server: cloudflare` with the challenge page. See [Bot challenges and sign-ins](#bot-challenges-and-sign-ins). | **Stop decrypting** the host |
| **Signing in through** host **fails while it's decrypted** (added in Cloak Proxy 0.4.2) | A decrypted sign-in was refused: Google's "This browser or app may not be secure" page, or 403s, 429s, timeouts or resets on a sign-in page. See [Bot challenges and sign-ins](#bot-challenges-and-sign-ins). | **Stop decrypting** the host |
| App **doesn't trust the Cloak Proxy certificate** | The app refuses the certificate on every host (at least three, or with an "unknown CA" alert) although macOS trusts it. Firefox, Java, Node.js, Python and Docker keep their own list of trusted certificates. | **Set up** app (Device & Runtime Setup) |
| Device **doesn't trust the Cloak Proxy certificate** | A device refused the certificate, or Cloak Proxy stopped decrypting for it after it refused three handshakes. | **Set up the certificate** (iPhone & iPad, certificate step) |
| Device **hasn't connected** | A device you named has sent nothing this session. | **Set up the device** |
| **No requests from** device **lately** | A device that sent traffic before has sent nothing for 15 minutes. Its Wi-Fi proxy may point elsewhere now, or it's on another network. | **Check the device setup** |
| **Other devices can't connect** | Cloak Proxy only listens on this Mac, and devices have used it before. | **Allow other devices** (restarts the proxy) |
| App**'s requests to** host **fail** | At least two connections or requests to a server failed in the last 30 minutes: DNS, refused, timed out, reset, unreachable, or the server's TLS. | **Show connections** |
| **The upstream proxy wants a username and password** (or **refuses connections**) (added in Cloak Proxy 0.4.2) | The external proxy in Settings › Network answered 407, 403 or a SOCKS5 refusal for connections in the last 30 minutes. See [Upstream proxy](#upstream-proxy). | **Check the upstream proxy** (Settings › Network) |
| **Looked up, but never connected** | See [Looked up, but never connected](#looked-up-but-never-connected). | None |

Connection evidence comes from the last 30 minutes.

## Certificate pinning

An app that pins certificates only accepts its own server's certificate, not the one Cloak Proxy makes for that host. When Cloak Proxy decrypts such a host, the app refuses the connection, and its requests fail. No proxy can decrypt a pinned connection without changing the app.

The Doctor reports pinning when an app refuses Cloak Proxy's certificate for the same host at least twice, never accepts it for that host, and the certificate is otherwise trusted: the app accepted it for other hosts, or macOS trusts it. It recognizes both ways apps refuse:

- A TLS alert during the handshake, such as "bad certificate" or "certificate unknown". The alert is shown in the evidence.
- A finished handshake followed by the app closing the connection within 1.5 seconds without sending anything. OkHttp and many SDKs check their pins after the handshake. Browsers' unused connections stay open longer, so they aren't counted.

An "unknown CA" alert means the app doesn't trust the certificate at all, which the Doctor reports separately.

**Stop decrypting these hosts** makes the app work again. A host listed exactly in [SSL Proxying](https://docs.subcloak.com/cloak-proxy/capture/ssl-proxying/) is removed from it. A host covered some other way (a wildcard such as `*.example.com`, SSL Proxying for the whole app, or a captured domain) is added to **Never decrypted** in **Settings › SSL Proxying**. Its connections then pass through encrypted and show as tunnels. Click **Decrypt again** there to undo it.

> **Caution:**
> To read a pinned app's traffic, turn pinning off in a debug build of your own app. Don't try to defeat pinning in apps you don't own or aren't authorized to test.

## Bot challenges and sign-ins

(added in Cloak Proxy 0.4.2)

Sites behind Cloudflare's bot protection, and the sign-in pages of Google, Microsoft, Okta and others, check that a connection comes from a real browser by its TLS and HTTP/2 fingerprint. When Cloak Proxy decrypts a connection it talks to the server with its own fingerprint, so these refuse it: Cloudflare answers **403** with a "Verify you are human" check that never passes, and Google says **This browser or app may not be secure** or the sign-in hangs.

From 0.4.2, the Doctor reports:

- **A bot challenge** when a decrypted request got Cloudflare's challenge page: the `cf-mitigated: challenge` header Cloudflare puts on every challenge, or a 403, 429 or 503 from `server: cloudflare` whose page loads the challenge platform. One is enough.
- **A failing sign-in** when a decrypted sign-in page was refused: Google's "This browser or app may not be secure" page (or a redirect to it) is enough on its own, and so is one 403, 429, timeout or reset on a built-in sign-in host you chose to **Decrypt anyway**. Elsewhere it takes two refusals on a page the browser opened on a sign-in host or path (`login.`, `sso.`, `/signin`, `/oauth2/`…), so one wrong password isn't reported. API calls to auth endpoints don't count.

The evidence says why each host is decrypted: **Decrypt anyway** for a built-in [sign-in host](https://docs.subcloak.com/cloak-proxy/capture/ssl-proxying/#sign-in-pages-and-bot-checks), the browser being in SSL Proxying › Apps, or the SSL Proxying rule that covers it. For a browser it suggests the [Capturing Browser](https://docs.subcloak.com/cloak-proxy/devices/capturing-browser/) instead.

**Stop decrypting** the host turns **Decrypt anyway** back off for a built-in sign-in host, removes a host listed exactly in SSL Proxying, or adds it to **Never decrypted** in **Settings › SSL Proxying** when a wildcard or the browser's own rule covers it. Its open decrypted connections close once their requests in flight finish, so the browser reconnects through an encrypted tunnel: reload the page or sign in again.

In 0.4.1 and earlier the Doctor doesn't report these. If a sign-in or a Cloudflare-protected site fails while its browser or host is decrypted, turn SSL Proxying off for it. See [Decrypting a browser](https://docs.subcloak.com/cloak-proxy/capture/ssl-proxying/#decrypting-a-browser).

## HTTP/3

HTTP/3 travels over QUIC, on UDP port 443. HTTP proxies only carry TCP, so no proxy, including Cloak Proxy, can see HTTP/3 requests. Most apps don't use HTTP/3 while a proxy is set, but apps with their own QUIC code can.

The Doctor finds these apps by looking at each app's sockets: an app with UDP sockets connected to port 443 of a public address (seen in two checks within 5 minutes) is listed with those addresses. It also notes when a server offered HTTP/3 in an `Alt-Svc` response header and the app then stopped sending it requests through Cloak Proxy for 2 minutes while still using other servers: **App may have switched to HTTP/3**.

**Capture its domains** opens the [capture sheet](https://docs.subcloak.com/cloak-proxy/capture/apps-that-ignore-the-proxy/). Captured domains resolve to Cloak Proxy, which doesn't accept QUIC, so most apps fall back to HTTPS over TCP within a moment and their requests show up. An app that only speaks HTTP/3 stays hidden.

(added in Cloak Proxy 0.5.0) From 0.5.0, with [App Capture](https://docs.subcloak.com/cloak-proxy/capture/capture-apps-that-ignore-the-proxy/#http3), the network extension refuses the picked apps' QUIC connections (**Block HTTP/3 for these apps**, on by default) and sends the HTTPS they fall back to through Cloak Proxy, without capturing any domains.

## VPNs

VPN apps such as Surfshark and PureVPN can change where traffic goes. The Doctor reads which VPNs macOS reports as connected and which network carries the default route.

| Situation | What the Doctor says |
|---|---|
| A VPN is connected and the macOS proxy still points at Cloak Proxy | A note. Apps still send traffic to Cloak Proxy, which reaches servers through the VPN. If requests stop arriving, turn off the VPN's options that block the local network or route around local proxies, or disconnect it while you capture. |
| A VPN is connected or carries all traffic, and the macOS proxy no longer points at Cloak Proxy | A problem: the VPN is the active network and has no proxy set. Click **Set the proxy again**. If it doesn't stick, disconnect the VPN while you capture. |

## Looked up, but never connected

For a [captured app](https://docs.subcloak.com/cloak-proxy/capture/apps-that-ignore-the-proxy/), the Doctor compares the lookups Cloak Proxy answered with the connections that arrived. A captured host looked up at least three times without any connection on port 443 or 80 is listed. The app may use another port (gRPC often uses 50051), which capture doesn't cover, or HTTP/3 only.

## Upstream proxy

(added in Cloak Proxy 0.4.2)

With an [external proxy](https://docs.subcloak.com/cloak-proxy/capture/network-settings/#send-traffic-through-another-proxy) set, Cloak Proxy 0.4.2 sends every connection it opens through it. When the proxy refuses, those requests and tunnels fail, so the Doctor reports it for this computer, with the hosts and the proxy's answer:

| Answer | What to do |
|---|---|
| **407 Proxy Authentication Required**, or a SOCKS5 proxy that wants or refuses credentials | Enter the username and password the proxy expects in **Settings › Network**, or correct them. |
| **403 Forbidden** or another refusal | The proxy's rules block those hosts. If they're reachable without it, add them to **Don't use it for**; otherwise ask whoever runs the proxy. |

**Check the upstream proxy** opens **Settings › Network**. A proxy that doesn't answer at all shows as an ordinary connection failure (**Connection refused**, **Timed out**) on the requests instead.

## Connections

The **Connections** view lists every recent connection to Cloak Proxy, newest first, including connections that failed before they became a request: a refused certificate, a server that can't be reached, a host that doesn't resolve.

*[Screenshot: The Connections view: a table of connections with time, app, host, kind, connect time, TLS time, version and ALPN, requests and result, including certificate rejections, connections closed after the handshake and refused connections. Every connection with its timings, including ones that never became a request.]*

| Column | Shows |
|---|---|
| **Time** | When the connection opened |
| **App** | The app or device that opened it |
| **Host** | Where it went, with the port when it isn't 80 or 443 |
| **Kind** | **HTTP**, **Tunnel** (HTTPS passed through), **Decrypted**, **SOCKS**, **Captured** (by DNS capture) or **Reverse proxy**; from 0.5.0 also **App capture**, **App capture, decrypted** or **App capture, raw TCP** for connections from [App Capture](https://docs.subcloak.com/cloak-proxy/capture/capture-apps-that-ignore-the-proxy/) (added in Cloak Proxy 0.5.0) |
| **Connect** | Time to connect to the server, including its DNS lookup, for tunnels Cloak Proxy relays; for other connections, the DNS lookup before the first request (`<1 ms` when the answer was cached) |
| **TLS** | For decrypted connections: the handshake with the app, the TLS version and the protocol agreed by ALPN (`h2` or `http/1.1`) |
| **Requests** | Requests sent on the connection |
| **Result** | **Open**, **Closed**, **Not recorded:** and why, or the failure: **DNS lookup failed**, **Connection refused**, **Timed out**, **Connection reset**, **Network unreachable**, **Server TLS failed**, **Certificate rejected** (with the TLS alert), **Closed during handshake** or **Closed after handshake** |

Type in the field to filter by host, app or failure, and check **Failed only** to see just the failures. Select a row to read the full error below the table. **Show connections** on a finding filters the view to that app; click the cross on its name to show every app.

Cloak Proxy keeps the newest 4,000 connections and the timings of the newest 20,000 requests in memory, and drops the oldest first. The log isn't saved with sessions.

## The Connection section in the inspector

The request's **Summary** tab, and the panel for an encrypted tunnel, end with a **Connection** section: the connection's kind and number, **Connect**, **TLS with the app** (time, version and ALPN), the **TLS alert** if the app refused the certificate, **Requests on it** (and how many weren't recorded, with the reason), and the **Failure**. For the request itself it adds **DNS**, **Server** (time from sending the request on to the response) or **Server failure**, and **HTTP/3** when the server offered it. A failed request has a **Why did this fail?** link that opens the Doctor for its app. See [Inspector](https://docs.subcloak.com/cloak-proxy/inspect/inspector/#summary).

The section appears for requests captured in this run while their connection is still in the log. Imported sessions don't have one.

> **Note:**
> For decrypted requests, Cloak Proxy's connection to the server is shared between requests, so the inspector shows the time to the response rather than the server's own connect and TLS times.

## Ask your AI assistant

The `diagnose_capture` tool in Cloak Proxy's [MCP server](https://docs.subcloak.com/cloak-proxy/automation/mcp-server/) returns the same findings as JSON, each with its kind, severity, explanation, hosts, evidence and suggested fix, plus the checks that passed and recent failed connections. Pass `app` to diagnose one app or device. The control API serves it as the `diagnose_capture` method of `POST /api/rpc`. See [MCP tools reference](https://docs.subcloak.com/cloak-proxy/automation/mcp-tools-reference/).

```bash title="Terminal"
cloakctl mcp   # then ask: "Why isn't ShopApp's traffic showing in Cloak Proxy?"
```

## What the Doctor can't see

- Traffic that never reaches this Mac, such as a phone on another network.
- Which proxy a device's Wi-Fi settings point at. The Doctor only knows that a device stopped sending requests.
- Raw TCP on ports other than 80 and 443, and UDP other than QUIC on port 443.
- The macOS proxy and VPN checks don't run in test mode (`CLOAK_SNAPSHOT`), which never touches the macOS proxy.

## Related

  - [Apps that ignore the proxy](https://docs.subcloak.com/cloak-proxy/capture/apps-that-ignore-the-proxy/): Capture apps that connect straight to the internet.
  - [SSL Proxying](https://docs.subcloak.com/cloak-proxy/capture/ssl-proxying/): Choose which hosts and apps are decrypted.
  - [Troubleshooting](https://docs.subcloak.com/cloak-proxy/reference/troubleshooting/): Common problems, their causes and fixes.
  - [Failed requests and tunnels](https://docs.subcloak.com/cloak-proxy/inspect/failed-requests-and-tunnels/): What failed rows and encrypted tunnels mean.
