Dartmole

Why Dartmole

Dartmole shows and changes the HTTP traffic of your own Flutter app, in the builds you and your testers install. Use it when you need to see what a tester's build sent, or to make a call fail or return different data without touching the backend.

The problem

Most tools for watching an app's traffic expect the app to use the phone's networking. Flutter apps mostly don't. Dart's HttpClient, which carries Dio, package:http and most of pub.dev, has its own networking:

  • It ignores the phone's Wi-Fi proxy, so a phone pointed at Charles or Proxyman still sends Dart's calls straight to the server.
  • It has its own rules for which certificates to trust, so installing a proxy's certificate on the phone doesn't help Dart either.

The usual fix is code in your app: an HttpOverrides that points Dart at your Mac's IP address, and often a badCertificateCallback that accepts any certificate. That leaves a choice. Either the code only runs in debug builds, and testers' builds can't be inspected, or it runs everywhere, and certificate checks are off in the build you ship.

Flutter DevTools avoids the setup, but only while a debugger is attached.

What Dartmole does differently

  • Only your app goes through it. The plugin gives your app's HttpClient the proxy, after you scan a QR code. The phone's settings stay as they are, and other apps are left alone.
  • TLS stays on. The plugin trusts Dartmole's certificate authority for its own client only. It never switches certificate checks off, and there is no certificate to install on the phone.
  • It works in any internal build, release builds included. A tester scans the QR code in the build they already have; no debugger, no cable, and no special build.
  • Mocks are files in your repository. A mock answers a call with the status, headers, body and delay you choose, and the backend never sees the request. Mocks live in .dartmole/mocks/, so they are reviewed in pull requests and reach your teammates when they pull. See Projects and mocks.

Compared with other tools

Flutter DevTools

DevTools' Network view shows the same calls while you run the app from flutter run or flutter attach, and it's already open in your IDE. For "what did that call just return?" while you're developing, it's often enough.

It needs the Dart VM service, which release builds don't include. A profile build keeps it, but reaching it still takes a cable or adb and the Flutter tools on your machine. The Network view also only shows calls; it can't change them.

Choose Dartmole to see calls from a build that isn't attached to your machine, such as a tester's, or to mock them. Keep DevTools for performance, memory and the widget tree, which Dartmole doesn't do.

Charles and Proxyman

Both are mature, general-purpose proxies. They see every app on the phone, including traffic from native code, and offer breakpoints, throttling and saved sessions.

For a Flutter app's own calls, they need the HttpOverrides code described above, and certificate setup on every device. Their mocking rules live in the tool on one person's machine.

Choose Dartmole when the calls you care about come from your Dart code, you want testers' builds covered without touching their phones, and your mocks should be shared through the repository. Choose Charles or Proxyman when most of the traffic comes from native SDKs, or when you need breakpoints and throttling.

mitmproxy

Dartmole runs mitmproxy underneath, so the interception is the same. On its own, mitmproxy needs the same device and HttpOverrides setup as Charles, and changes traffic through Python scripts. Dartmole adds the pairing, a Mac app, and mocks as files you can read in a review.

Choose mitmproxy when you want to script the traffic yourself.

When Dartmole isn't the right tool

  • Most of the traffic is native. Firebase, flutter_appauth, WebViews and other plugins with native code bypass Dart's HttpClient. Dartmole can show them with the phone's proxy and certificate set up, as described in Native traffic, but that is the same setup a general-purpose proxy needs.
  • The phone and the Mac can't be on the same network. On Android, a USB cable works around this; see Getting started.
  • You can't add a dependency to the app. Without the plugin, Dartmole works like any other proxy, through native traffic setup, and doesn't see Dart's calls.
  • The app runs on the web. The browser's own developer tools already show every call.

Not in Dartmole yet

Dartmole is in beta, and some things are missing for now rather than by design:

  • Breakpoints and throttling. Dartmole shows and mocks calls, but can't pause one to edit it, or slow the whole connection down. A mock's delay covers a single slow call.
  • WebSockets and gRPC. Only HTTP calls are shown.
  • Saved sessions. The calls on the Proxy tab are gone when you quit.
  • Other platforms. Dartmole runs on macOS 12 or later, on Apple silicon only.

Using them together

The tools overlap less than it seems. A common split:

  • DevTools while developing with flutter run, and for performance and memory.
  • Dartmole for internal builds on testers' phones, and for mocking backend states such as errors, empty lists and slow responses.
  • A general-purpose proxy for the native SDKs whose traffic Dartmole doesn't see without extra setup.

Ready to try it? Getting started sets up both parts.