Ticker

6/recent/ticker-posts

How to Record Flutter App Traffic in JMeter Using Charles Proxy – Full Setup Guide

How to Record a Flutter App with JMeter using Charles Proxy

Recording a Flutter App with JMeter + Charles Proxy

JMeter Charley Configuration for Flutter App

As a tester, you might get stuck when asked to do performance testing of a Flutter app—especially if you're not given API endpoints and are expected to record traffic directly from the frontend UI. The usual method of using JMeter's HTTP(S) Test Script Recorder doesn't work because JMeter alone can’t capture traffic from Flutter apps easily. Don’t worry! Today, we’re here with a solution just for testers like you. With the help of Charles Proxy sitting in the middle, we’ll show you how to record and replay that traffic in JMeter. Let’s begin and get it done in the next 5 to 10 minutes!

Table of Contents

  1. Prerequisites
  2. Install & configure Charles
  3. Install the Charles root certificate on Android / iOS
  4. Make your Flutter app proxy-aware
  5. Set up JMeter’s HTTP(S) Recorder
  6. Chain Charles → JMeter (up-stream proxy)
  7. Record, verify & export
  8. Optional — convert a HAR/CHLS session to JMeter
  9. Troubleshooting & FAQ

1  Prerequisites

  • Apache JMeter 5.6+ installed on your desktop machine.
  • Charles Proxy (v4.6+ recommended).
  • An Android emulator/device or iOS simulator/device running your Flutter build.
  • Desktop and device must be on the same Wi-Fi or routed network.

2  Install & configure Charles (macOS & Windows)

  1. Install Charles:
    • macOS: Use Homebrew or download from the official site.
      brew install --cask charles
    • Windows: Download the .exe installer from the Charles website and run it as administrator.
    Charles Install Screenshot
  2. Configure proxy settings:
    Go to Proxy ▸ Proxy Settings and confirm Charles is listening on port 8888. Charles Proxy Settings Screenshot
  3. Enable SSL Proxying:
    Go to Proxy ▸ SSL Proxying Settings and add `*:*` as location.
    This ensures Charles decrypts all SSL/TLS traffic. SSL Proxy Settings Screenshot

3  Install the Charles root certificate on the device

Charles generates a unique root CA (charles-proxy-ca.pem). You need your device/emulator to trust that CA so TLS handshakes succeed.

iOS Simulator / Device
  1. On the simulator, simply visit https://chls.pro/ssl in Safari and accept the profile (Settings ▸ General ▸ About ▸ Certificate Trust Settings → enable).
Android 7 +
  1. Open Help ▸ SSL Proxying ▸ Save Charles Root Certificate and save it as charles.pem.
  2. Push it to /sdcard/Download and install it (Settings ▸ Security ▸ Encryption & credentials ▸ Install from storage).
  3. Add a network_security_config.xml file that tells your debug build to trust user CAs:
  4. <network-security-config>
      <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
          <certificates src="system"/>
          <certificates src="user"/>
        </trust-anchors>
      </base-config>
    </network-security-config>

    Add android:networkSecurityConfig="@xml/network_security_config" in AndroidManifest.xml.:contentReference[oaicite:2]{index=2}

4  Make your Flutter app proxy-aware (Perform this step when your charle proxy doesn't record your traffic)

Flutter (Dart) ignores the system proxy, so you must inject it manually. The simplest approach is to read the proxy from the environment and override HttpClient.findProxy:

/// pubspec.yaml
dependencies:
  http: ^1.2.1
  system_proxy: ^0.2.2
import 'dart:io';
import 'package:system_proxy/system_proxy.dart';

class ProxiedHttpOverrides extends HttpOverrides {
  final String host;
  final String port;
  ProxiedHttpOverrides(this.host, this.port);

  @override
  HttpClient createHttpClient(SecurityContext? context) {
    return super.createHttpClient(context)
      ..findProxy = (_) => 'PROXY $host:$port'
      ..badCertificateCallback = (cert, host, port) => true; // trust Charles CA
  }
}

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final proxy = await SystemProxy.getProxySettings();
  if (proxy != null) {
    HttpOverrides.global =
        ProxiedHttpOverrides(proxy['host']!, proxy['port']!);
  }
  runApp(const MyApp());
}

Now every HTTP call made with http, dio, gRPC, etc., obeys the proxy.:contentReference[oaicite:3]{index=3}

5  Set up JMeter’s HTTP(S) Test Script Recorder

  1. Start JMeter and add
    Test Plan ▸ Add ▸ Non-Test Elements ▸ HTTP(S) Test Script Recorder. The default port is 8889 – leave it or pick another free port.:contentReference[oaicite:4]{index=4}
  2. Under Target Controller, point to where you want recorded samplers to land (e.g. a dedicated Recording Controller).
  3. Click Start. JMeter creates ApacheJMeterTemporaryRootCA.crt in the bin folder.

6  Chain Charles → JMeter (up-stream proxy)

We want traffic to flow:

Flutter App ► Charles Proxy (8888) ► JMeter Recorder (8889) ► Internet

  1. In Charles: Proxy ▸ External Proxy Settings.
    Enable HTTP and set hostname to your desktop’s IP, port to JMeter’s recorder port (8889).:contentReference[oaicite:5]{index=5}
  2. Restart recording in both tools.

7  Record & verify

  1. Launch your Flutter app and exercise an end-to-end flow.
  2. In Charles you should see each request; in JMeter, matching samplers appear under the Recording Controller.
  3. Stop recording, tidy up (remove third-party analytics calls, etc.), add assertions and thread groups, then save the plan.

8  Optional — convert a HAR / CHLS session to JMeter

If chaining feels fiddly, you can:

  1. File ▸ Export Session ▸ HAR (HTTP Archive) in Charles.
  2. Upload the HAR to the BlazeMeter HAR-to-JMX converter or use jmeter-har-reader on the CLI to spit out a ready-to-run .jmx.

9  Troubleshooting | FAQ

  • No traffic in JMeter: double-check the External Proxy field in Charles and that the JMeter recorder is Started.
  • Flutter app throws CERT errors: ensure badCertificateCallback returns true (Dart trusts Charles’ self-signed cert) and that the Android network security config includes <certificates src="user"/>.
  • Large uploads stall: bump jmeter.properties ▸ proxy.transmit.buffer to 1-2 MB.
  • Need to record multiple devices concurrently: give each device its own Charles port and spin up matching JMeter recorders on different ports (e.g. 8890, 8891…).

If You Find any difficulties to configure you can just comment here ! You will surely get your response with solution.

Post a Comment

0 Comments