Skip to content
| Marketplace
Sign in
Visual Studio Code>Debuggers>Flutter InterceptNew to Visual Studio Code? Get it now.
Flutter Intercept

Flutter Intercept

Abdulrahman Obaid

|
4 installs
| (0) | Free
Inspect, pause, edit, block and mock your Flutter app's HTTP traffic — no code in your app, no setup. Just press F5.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Flutter Intercept

View, pause, edit, block and mock your Flutter app's HTTP traffic, right inside VS Code. You add no code to your app and there's nothing to set up: install the extension, press F5 as usual, and the traffic shows up.

Traffic panel: live list of requests with a JSON response open

  • Works with Dio, package:http and plain HttpClient, which covers anything built on dart:io.
  • HTTPS works too, and you don't install a certificate on the device, simulator or Mac.
  • Your app's code is never changed. Nothing is added to pubspec.yaml, and flutter build / CI never see the tool.

How it works

  1. When you start a Flutter (or Dart) debug session, Flutter Intercept writes a small launcher to .dart_tool/flutter_intercept/entry_<name>.dart and runs that instead of lib/main.dart (or your flavor target). Flutter's default .gitignore already ignores .dart_tool/.
  2. The launcher installs HttpOverrides, which send every HttpClient to a proxy on your machine (PROXY <host>:<port>; DIRECT), and makes the app trust that proxy's certificate authority. It then calls your real main().
  3. A man-in-the-middle proxy inside the extension records each exchange and applies your rules. The panel at the bottom of VS Code shows the traffic.
  4. If the proxy isn't reachable, requests go DIRECT and the app keeps working. Builds made outside VS Code (flutter build, flutter run in a terminal, CI) are untouched.

Features

Live traffic list

  • Every request shows its method, status, host, path, time, size and state (paused, mocked, blocked, error).
  • Filter by URL text, method, status class (2xx–5xx, errors) or paused only.
  • Keyboard navigation and a resizable detail pane.

Request and response details

  • Headers and bodies. gzip/deflate/br are decoded, JSON shows as a collapsible tree, binary bodies show their size, and images get a preview.

Breakpoints

  • Pause a request before it reaches the server, or a response before your app receives it.
  • Edit the method, URL, headers and body (request) or the status, headers and body (response), then Resume with edits, Resume unchanged or Abort.
  • JSON bodies are validated as you type.
  • A countdown shows when an untouched breakpoint auto-resumes (after 5 minutes).

Paused response with an editable JSON body and Resume/Abort actions

Mock and block

  • Answer requests with a mock (status, headers, body, optional delay) or block them (connection reset or an error status). Neither contacts the server.
  • Mock this, Block this and Break on this turn any recorded exchange into a rule in one click. The new rule goes to the top, and a mock opens in the editor so you can change its body.

“Mock this” creates a rule from the response and opens it for editing

Rules

  • Each rule matches on method plus URL. The URL is a glob such as https://api.example.com/users/* or a /regex/.
  • Rules run top to bottom and the first enabled match wins. The list shows which rules are shadowed by an earlier one.
  • Reorder, enable/disable, delete with undo. Rules are saved per workspace.

Rules tab: ordered rules with enable toggles and match counts

Status bar

  • Intercept: on/off toggles interception for new sessions. It shows · LAN while an iPhone session runs.
  • A pause counter appears while exchanges are waiting at a breakpoint.

The panel follows your VS Code theme: light, dark and high contrast.

Traffic panel in a light theme

Devices

Target What happens
Android emulator The app reaches the proxy at 10.0.2.2. No setup.
Android physical device (via adb) Flutter Intercept runs adb reverse for the proxy port and removes it when the last session ends. adb is found through ANDROID_HOME/ANDROID_SDK_ROOT, the default SDK location, or PATH.
iOS simulator Uses localhost. No setup.
macOS desktop Uses localhost. The app needs the com.apple.security.network.client entitlement, which any macOS app that already does networking has.
Plain Dart programs (bin/main.dart) Intercepted the same way.
iPhone (physical) Supported, after some one-time setup; see iPhone below. Verified over Wi-Fi. On Apple Silicon Macs, a USB connection also needs Rosetta.
Flutter web Not supported (no dart:io). The session is left untouched.

Hot reload, hot restart, flavors (lib/main_dev.dart etc.) and --profile keep working through the generated entry. Release launches (flutterMode: "release" or --release) are never intercepted. They run your normal entry point.

iPhone

A physical iPhone can't reach your Mac's localhost. So while an iPhone debug session runs, and only then:

  • The proxy also listens on your Mac's Wi-Fi/LAN IPv4 address.
  • The status bar shows Intercept: on · LAN, and the Traffic panel shows LAN open for iPhone · <ip>:<port>.

The LAN listener is protected:

  • Secret token. Each opening gets a fresh random token, which only the app launched in that session receives (as a build define). Requests without it get 407 and the connection is closed. The token never appears in the UI or the extension's log.
  • No access to your Mac. Requests from the phone aimed at the Mac itself (its own addresses, localhost, link-local) are refused with 403.
  • Locked to your iPhone. The listener only accepts the first device that connects with the token, and the status tooltip shows locked to <ip>.
  • Private networks only. It only listens on a private (RFC 1918) address: 10.x, 172.16–31.x or 192.168.x.
  • Closes automatically. The listener closes when the last iPhone session ends, or as soon as your Mac's network changes (new address, or a different Wi-Fi/router). After a network change, relaunch the iPhone session. Everything else stays on 127.0.0.1.

Verified on an iPhone 16 Pro Max (iOS 27) over Wi-Fi, in debug and profile mode.

One-time setup

  1. Xcode → Settings → Accounts: add the Apple Account of your signing team, and select that team for the app (automatic signing works).
  2. On the iPhone, the first time you install an app signed by your account: Settings → General → VPN & Device Management → your developer certificate → Trust.
  3. On the iPhone, when the app first starts: allow it to find and connect to devices on your local network.
  4. On the Mac, the first time the LAN listener opens: allow Visual Studio Code to accept incoming network connections. Also allow Local Network access for VS Code if macOS asks.

Flutter Intercept reminds you of steps 3 and 4 once.

Good to know

  • Network. The iPhone must be on the same Wi-Fi as the Mac, and unlocked while the app installs and launches. If your Mac has no private Wi-Fi/Ethernet IPv4 address (none at all, a public address, or carrier-grade NAT 100.64.x), the session runs without interception and you get a warning.
  • Use a trusted Wi-Fi. The token travels unencrypted inside the proxy request. On shared or public Wi-Fi, others on the network may be able to observe it.
  • Apple Silicon Macs and USB. Flutter's bundled iproxy, which a USB iPhone needs, is x86_64-only. So a USB iPhone needs Rosetta: sudo softwareupdate --install-rosetta --agree-to-license.
    • The alternative is to pair the iPhone over Wi-Fi (Xcode → Window → Devices and Simulators → Connect via network). Wireless runs don't use iproxy.
    • Flutter Intercept warns you before launching on a USB iPhone when Rosetta is missing.
  • Stale token. If a build launched with an old token keeps running after the listener was reopened, its HTTPS goes direct (not intercepted) and plain http:// requests get 407. Relaunch the session to fix it. The extension keeps the token stable while any iPhone session is alive.
  • Free signing teams. A personal (free) team's provisioning profile expires after 7 days. Rebuild to renew it.
  • Wireless launches are slower. The first debug launch over Wi-Fi can take around 40 s to install and start.

Use with AI agents

AI coding agents can use Flutter Intercept the way you do. They can run the app, watch its requests, check what was sent, and fake server responses to test error states. This works with GitHub Copilot (agent mode), Claude Code, Cursor, and any client that speaks MCP (Model Context Protocol).

What the agent can do Tool
See whether the proxy and app sessions are running get_status
List recent requests (filter by URL, method, status, state) list_requests
Read one request in full (headers, bodies, timings, error) get_request
Wait until the app makes a matching request (with a timeout) wait_for_request
See requests paused at a breakpoint list_paused
List the rules in priority order list_rules
Answer matching requests with a mock (status, headers, body, delay) add_mock
Block matching requests add_block
Pause matching requests or responses add_breakpoint
Remove a rule remove_rule
Resume a paused request, optionally with edits, or abort it resume_request, abort_request
Clear the recorded traffic clear_requests
Save the traffic as a HAR file in .dart_tool/flutter_intercept/exports/ export_har
Launch the app through Dart-Code, stop it, or hot-restart it launch_app, stop_app, hot_restart

In VS Code the tools are named flutter_intercept_<tool>; over MCP they use the names above.

Connecting

  • GitHub Copilot (agent mode in VS Code): nothing to set up. The tools are available as soon as the extension is installed.
  • Claude Code, Cursor and other MCP clients:
    1. Run Flutter Intercept: Connect AI agent and pick your client.
    2. The command copies the setup to the clipboard: the claude mcp add … command for Claude Code, an mcp.json snippet for Cursor, or the URL and header for other clients.
    3. Paste it into your client. The command never writes config files itself.
  • The MCP server runs at http://127.0.0.1:<port>/mcp (default port 47823) and accepts only local connections that carry its secret token.

Access, confirmations and secrets

  • Access level. flutterIntercept.agent.access decides what agents may do:

    • readWrite (the default);
    • readOnly: agents can look, but changes are refused;
    • off: nothing is exposed.
  • Confirmations. Every tool that changes something asks you to confirm in the client: adding or removing rules, resuming or aborting requests, clearing traffic, and launching, stopping or restarting the app.

  • Secret redaction. With flutterIntercept.agent.redactSecrets on (the default), agents see [redacted] instead of:

    • authorization, cookie and token-like headers;
    • password, token, key and session fields in URLs and JSON bodies.

    Redaction only affects what agents read. Your app always receives the real values.

  • What agents never see: Flutter Intercept's CA key, the iPhone LAN token, or the MCP token.

  • Agent rules are marked. Rules an agent creates are named [agent] …. They get an agent badge in the rules list and on the requests they match.

  • The status line shows whether an agent is connected and its last tool call, for example Agent: connected · last: wait_for_request 3s ago.

Teach your agent the workflow

Run Flutter Intercept: Add AI Agent Instructions and pick AGENTS.md, CLAUDE.md and/or .github/copilot-instructions.md. It adds a short section that tells agents:

  • to verify changes against real traffic: launch the app, then wait_for_request, then get_request;
  • to test error states with mocks;
  • to clean up the rules they add.

The section sits between <!-- flutter-intercept:start --> and <!-- flutter-intercept:end --> markers. Running the command again updates it in place, and the rest of the file is left alone.

Example prompts

  • "Run the app and check that the login request sends the email and password."
  • "Make the products endpoint return 500 and check that the error UI shows up, then remove the mock."
  • "Mock the feed endpoint with a 10-second delay and check the loading state."
  • "Pause the next checkout request, change the quantity to 3, and resume it."

Settings and commands

Setting Default Description
flutterIntercept.enabled true Route the HTTP traffic of Dart/Flutter debug sessions through Flutter Intercept. When off, sessions launch untouched.
flutterIntercept.port 8899 Port of the local proxy. If it's busy, the next free port up to 8999 is used. A change applies at the next launch when no intercepted session is running.
flutterIntercept.agent.access readWrite What AI agents may do: readWrite, readOnly or off. See Use with AI agents.
flutterIntercept.agent.redactSecrets true Show secrets (auth headers, cookies, tokens, passwords) to agents as [redacted].
flutterIntercept.agent.mcpPort 47823 Port of the local MCP server for agents. If it's busy, the next free port is used.
Command What it does
Flutter Intercept: Open Traffic Panel Shows the Traffic panel. It also opens by itself on the first intercepted session.
Flutter Intercept: Toggle Interception Same as clicking Intercept: on/off in the status bar.
Flutter Intercept: Clear Traffic Clears the list. Requests still in flight stay.
Flutter Intercept: Debug with Intercept Starts an intercepted debug session directly. A fallback if F5 isn't picked up.
Flutter Intercept: Connect AI agent Copies the setup for Claude Code, Cursor or another MCP client to the clipboard.
Flutter Intercept: Add AI Agent Instructions Adds or updates the Flutter Intercept section in AGENTS.md, CLAUDE.md or .github/copilot-instructions.md.

Limitations

What isn't intercepted, or behaves differently while intercepting:

  • Flutter web: it has no dart:io.
  • Native HTTP stacks: cronet_http, cupertino_http, native_dio_adapter. They bypass dart:io.
  • Background isolates (compute, Isolate.spawn): HttpOverrides apply per isolate, so clients created there go direct.
  • Apps that install their own HttpOverrides zone (HttpOverrides.runWithHttpOverrides or runZoned around their code): the inner zone wins.
    • Setting HttpOverrides.global is fine: your overrides still apply underneath.
    • Setting findProxy on a client is also fine: Flutter Intercept ignores the assignment and prints a note.
  • Dio validateCertificate pinning: Dio checks the certificate it receives, which is the proxy's, so those requests fail with bad certificate while intercepting. Turn interception off to test pinning.
  • mTLS (client certificates): the proxy can't present your app's client certificate to the server.
  • A custom connectionFactory that ignores the proxy host and port bypasses the proxy.
  • Long breakpoints and client timeouts: if your app's own timeout fires while a request is paused (for example Dio's receiveTimeout), the app gives up. The exchange is then marked "gave up" and can't be resumed. Raise the timeout in debug builds if you need long pauses.
  • What the panel keeps: bodies are shown up to 5 MB, after which they're marked truncated. Recorded traffic is cleared when the window reloads; rules are kept.

Security

  • Loopback only, except during iPhone sessions. The proxy listens on 127.0.0.1. Only while a physical iPhone session runs does it also listen on your Mac's private LAN address. That listener requires the session's secret token, locks to the first device that connects with it, and refuses requests aimed at the Mac itself. It closes when the session ends or the network changes (see iPhone).
    • Use it on a trusted Wi-Fi. On shared or public Wi-Fi, others may observe the token.
    • The token reaches disk. It is a build define, so flutter_tools writes it into ios/Flutter/Generated.xcconfig and ios/Flutter/flutter_export_environment.sh (both gitignored by default) and into the debug app. It is only usable while that session's listener is open, and only from the device it locked to.
  • AI agent access is local and gated. The MCP server for agents listens on 127.0.0.1 only.
    • Every request must carry a secret token, which is kept in VS Code's secret storage. Requests from browsers (an Origin header or a foreign Host) are refused.
    • Changes need your confirmation, and flutterIntercept.agent.access can make access read-only or turn it off.
    • Secrets are redacted in everything agents read. See Use with AI agents.
  • Only sessions you launch from VS Code while interception is on.
    • It doesn't attach to running apps.
    • It leaves test runs and web sessions alone.
    • It never intercepts release launches.
  • The app trusts one certificate authority. It doesn't accept arbitrary certificates.
    • On first use the extension creates a CA unique to your installation. It's stored in VS Code's extension storage on your Mac, readable only by your user.
    • The generated launcher makes the app trust that CA in intercepted sessions. Nothing is installed in any system trust store.
    • If the proxy isn't reachable, the DIRECT fallback keeps normal TLS verification.
  • Your own pinning:
    • While the proxy is up, pinning via badCertificateCallback or SecurityContext(withTrustedRoots: false) doesn't block interception.
    • With the proxy down, your pinning behaves exactly as without the tool.
    • Dio validateCertificate pinning still fails while intercepting (see Limitations).
  • The real server's certificate is still verified. By default the proxy checks it, so a bad certificate upstream still fails, and the app gets a 502 that carries the error.

Requirements

  • VS Code 1.90 or newer.
  • The Dart extension (Dart-Code.dart-code). It's installed automatically as a dependency, and it's what F5 runs.
  • A Flutter SDK (or Dart SDK for console apps). The generated launcher is tested with Dart 3.0 to 3.13 (Flutter 3.10 and newer).
  • For Android physical devices: adb (part of the Android SDK platform-tools).
  • For iPhones: Xcode with a signing team (see iPhone).
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft