# Flutter

> Capture a Flutter app's HttpClient traffic with a debug-only HttpOverrides file that sets the proxy and trusts the Cloak Proxy certificate.

Source: https://docs.subcloak.com/cloak-proxy/devices/flutter/

Added in Cloak Proxy 0.4.0.

Dart's `HttpClient` ignores the system proxy on every platform, so a Flutter app's requests never reach Cloak Proxy on their own, even with the Wi-Fi proxy or macOS capture on. Cloak Proxy gives you a small Dart file that, in debug builds only, sends `HttpClient` traffic to the proxy and trusts the Cloak Proxy certificate. The certificate is in the file, so you don't install anything on the device or simulator.

*[Screenshot: The Flutter page of Device & Runtime Setup: the generated lib/cloak_proxy_overrides.dart with Save to Project, the two lines to add to main(), and a device picker with the flutter run command. The Flutter page: the file, the call in main(), and the run command.]*

## Add the file

1. Open **Proxy › Device & Runtime Setup…** and choose **Flutter**.

2. Click **Save to Project…** and pick your Flutter project (the folder with `pubspec.yaml`). Cloak Proxy writes `lib/cloak_proxy_overrides.dart`.

   Or click **Copy** and save it yourself.

## Call it from main()

Add the import and call `install()` before anything makes a request:

```dart title="lib/main.dart"
import 'cloak_proxy_overrides.dart';

void main() {
  CloakProxyOverrides.install();
  runApp(const MyApp());
}
```

## Run with the proxy address

`install()` does nothing unless the run passes the proxy's address with `--dart-define`. Pick where the app runs on the page to get the command:

**iOS Simulator or macOS**

```bash title="Terminal"
flutter run --dart-define=CLOAK_PROXY=127.0.0.1:9090
```

The simulator shares the Mac's network, so `127.0.0.1` is the Mac.

**Android emulator**

```bash title="Terminal"
flutter run --dart-define=CLOAK_PROXY=10.0.2.2:9090
```

The emulator reaches the Mac at `10.0.2.2`.

**Android over USB**

```bash title="Terminal"
adb reverse tcp:9090 tcp:9090
flutter run --dart-define=CLOAK_PROXY=127.0.0.1:9090
```

`adb reverse` makes `127.0.0.1` on the device reach the Mac. **Connect Proxy** on the [Android](https://docs.subcloak.com/cloak-proxy/devices/android/) page runs it for you.

**Phone on Wi-Fi**

```bash title="Terminal"
flutter run --dart-define=CLOAK_PROXY=192.168.1.20:9090
```

Use your Mac's address on the network, and turn on **Settings › Network › Allow other devices to connect**.

In VS Code or Android Studio, add `--dart-define=CLOAK_PROXY=…` to the launch configuration's arguments. The debug console prints `Cloak Proxy: HttpClient traffic goes through …` when it's on.

## What it covers

The file installs an `HttpOverrides` that, for every `HttpClient` the app creates:

- sends requests to the proxy with `findProxy`;
- trusts the Cloak Proxy certificate with `SecurityContext.setTrustedCertificatesBytes`, on top of the usual roots. Certificates are still checked: only ones Cloak Proxy issued, or ones the system already trusts, are accepted.

That covers `package:http`, Dio, `Image.network`, `NetworkImage` and anything else built on `dart:io`'s `HttpClient`.

| Build | What happens |
|---|---|
| Debug, with `--dart-define=CLOAK_PROXY` | Traffic goes through Cloak Proxy |
| Debug, without the define | Nothing changes |
| Profile and release | Nothing changes: `kDebugMode` is false, so the code is compiled out |

Only Cloak Proxy's public certificate is in the file. It's safe to commit; the comment at the top shows its SHA-256 fingerprint, which you can compare with **Settings › Certificate**. If you regenerate the certificate, save the file again.

## From MCP and the command line

[`capture_config`](https://docs.subcloak.com/cloak-proxy/automation/mcp-tools-reference/#capture_config) with `kind: "flutter"` returns the file and the run command for `device` (`ios_simulator`, `android_emulator`, `android_usb` or `device`); with `project` and `write: true` it writes the file. `capture_setup` with `target: "flutter"` and `apply: "flutter-snippet"` does the same as a setup step.

```bash title="Terminal"
cloakctl capture-config flutter --project ~/code/shop_app --write
cloakctl capture-config flutter --device android_emulator
```

## Limits

- `cupertino_http` and `cronet_http` use the platform's own networking instead of `HttpClient`. They follow the device's proxy and trust store like a native app: see [iOS Simulator](https://docs.subcloak.com/cloak-proxy/devices/ios-simulator/) or [Android](https://docs.subcloak.com/cloak-proxy/devices/android/).
- WebSockets made with `WebSocket.connect` use `HttpClient` and are covered; `web_socket_channel` on the web isn't, as Flutter web runs in the browser (use a [capturing browser](https://docs.subcloak.com/cloak-proxy/devices/capturing-browser/)).
- gRPC through `grpc-dart` opens its own HTTP/2 connections and ignores `HttpOverrides`.

## Related

  - [Android](https://docs.subcloak.com/cloak-proxy/devices/android/): Point an emulator or USB device at the proxy.
  - [iOS Simulator](https://docs.subcloak.com/cloak-proxy/devices/ios-simulator/): Capture apps in the simulator.
  - [Doctor](https://docs.subcloak.com/cloak-proxy/capture/doctor/): Find out why an app's traffic isn't showing.
