Capture on Android
Hodor now runs natively on Android. Instead of relying on the system HTTP
proxy, Hodor captures traffic at the IP layer through a VPN (VpnService)
tunnel, so it sees what proxy-based tools cannot — including traffic from
Flutter apps and native apps that deliberately bypass the system proxy.
This page explains two things end to end:
- What Hodor can decrypt on Android — the HTTPS decryption capability matrix, and why it depends on the target app and where the certificate lives.
- How to get it working — the two deployment paths (a phone, or an emulator with the free HodorTrust tool) and the exact steps for each.
Download
- Hodor for Android (APK) — get it on the download page. Requires Android 10 (API 29) or later, on 64-bit devices only.
- HodorTrust (cert tool for emulators/rooted devices) — get it on the download page. Requires macOS 12 or later (Intel & Apple Silicon) or Windows 10/11 (64-bit).
How capture works on Android
- Hodor establishes a
tuninterface via the built-in VPN. All traffic — Wi-Fi or cellular — is redirected into Hodor and can be recorded, inspected, rewritten and scripted, exactly like on iOS and macOS. - Because it is
VpnService(TUN) based, Hodor is naturally immune to the classic proxy blind spots: apps that ignoreHTTP_PROXY, and Flutter's DartHttpClient, which bypasses the system proxy entirely. - HTTPS decryption requires a Man-in-the-Middle (MITM) certificate. Whether a given app accepts that certificate is what the matrix below describes.
HTTPS decryption capability matrix
Decrypting an HTTPS session needs two conditions at the same time:
- Engine side — Hodor has a usable CA, so its VPN engine actually performs MITM for the target host. If no certificate is installed at all, the engine transparently forwards HTTPS without trying to decrypt it (the app keeps working, but you see no plaintext).
- Client side — the target app must trust Hodor's CA. This is where Android differs sharply between app types and between a user certificate and a system certificate.
On Android a certificate can live in one of two places:
- User certificate — installed through Settings → Security → Install a
certificate (no root required). Stored in the Android keystore
(
/data/misc/keychain). - System certificate — written into the system trust store
(
/system/etc/security/cacerts, and the APEXconscrypt/cacertson Android 14+). Requires a rooted device or an emulator.
| Target app | User cert (no root) | System cert (root / emulator) |
|---|---|---|
| Plain HTTP (no TLS) | ✅ decrypt not applicable — always visible | ✅ |
Native app that declares trust for user certs (NSC network_security_config, or targetSdk < 24) | ✅ | ✅ |
| Normal third-party release app (no trust declaration) | ❌ handshake rejected → forwarded, no plaintext | ✅ |
Flutter / dart:io apps | ❌ dart:io ignores the user store entirely | ✅ (reads the system store) |
| Apps with certificate pinning | ❌ | ❌ (pinning is the real ceiling) |
- “A debug build trusts user certs automatically.” It does not. On Android
7.0+ a debuggable build without an explicit
network_security_configstill rejects an untrusted MITM cert. Trust is driven by NSC /targetSdk, not bydebuggable. - “Flutter can never be decrypted.” Also not true.
dart:ioreads its trust anchors directly from/system/etc/security/cacerts. Once Hodor's CA is in the system store (rooted device or emulator), Flutter apps decrypt exactly like native ones. The only genuine limitation is certificate pinning.
Which path should you use?
Path A — A real phone, no root
Use this when you debug your own app (or apps you can reconfigure).
-
Install the Hodor APK and enable its VPN in the app — traffic now flows through Hodor.
-
Install Hodor's CA as a user certificate (the app's certificate screen walks you through Settings → Security → Install certificate). See the general Install Certificate guide.
-
Make the target app trust that user certificate:
-
Native app — add a
network_security_config.xmlthat trusts user certs, referenced from your manifest:<!-- res/xml/network_security_config.xml --><network-security-config><debug-overrides><trust-anchors><certificates src="user" /></trust-anchors></debug-overrides></network-security-config> -
Flutter /
dart:ioapp — a user certificate is invisible todart:io, so bundle Hodor's CA into the app viaSecurityContextinstead:import 'dart:io';import 'package:dio/dio.dart';import 'package:dio/io.dart';import 'package:flutter/services.dart' show rootBundle;final caBytes = (await rootBundle.load('assets/hodor_ca.pem')).buffer.asUint8List();HttpClient createHttpClient() {final ctx = SecurityContext(withTrustedRoots: true)..setTrustedCertificatesBytes(caBytes);return HttpClient(context: ctx);}final dio = Dio()..httpClientAdapter = IOHttpClientAdapter(createHttpClient: createHttpClient);withTrustedRoots: truekeeps normal validation intact and only adds Hodor's CA. Export the CA from Hodor's certificate screen. Keep this change in debug/test builds, not in production releases.
-
Path B — Emulator or rooted device (full decryption)
Use this to capture any app (its own, or a third-party release build) with HTTPS fully decrypted. The trick is to place Hodor's CA in the system trust store — which needs root — and that is exactly what HodorTrust automates.
HodorTrust (Android certificate tool)
HodorTrust is a small macOS app that injects Hodor's CA into the Android system certificate store, so every app — native and Flutter alike — trusts it. It supports two modes:
-
One-click setup — from a clean machine to a decryptable emulator without ever opening a terminal. HodorTrust walks through eight stages, showing progress for each and letting you retry any single step:
- Check the environment (Android SDK, emulator,
adb). - Download the Google APIs system image.
- Create the AVD.
- Boot the emulator and wait for it to come online.
- Confirm root.
- Install the Hodor APK.
- Extract Hodor's CA certificate.
- Inject the CA into the system trust store.
Large components (image, AVD, Hodor, cert) are installed only once — already satisfied steps are skipped on the next run.
- Check the environment (Android SDK, emulator,
-
Inject into an existing rooted device — point it at any already-rooted emulator or device (Magisk,
adb root, LineageOS in a VM, …) and it scans connected devices, lets you pick the target, then injects — or reverts — the system certificate in seconds.
Requirements
- macOS 12+ (Apple Silicon recommended, since the AVD image is
arm64-v8a). - For one-click setup: an Android SDK with
cmdline-tools,platform-toolsand theemulator. HodorTrust prompts to download the Google APIs system image if it is missing. (The existing rooted device mode only needsadb.) - HodorTrust is Developer ID signed and notarized, so it opens without any Gatekeeper warnings.
HodorTrust is available for macOS (12 or later, Intel & Apple Silicon) and Windows 10/11 (64-bit) — both cover the same one-click emulator setup and existing-rooted-device injection.
Getting started
- Get HodorTrust from the download page, open it, then drag the app to your Applications folder. HodorTrust is signed and notarized for Gatekeeper.
- Pick a mode:
- One-click setup for a fresh emulator, or
- Existing rooted device if you already have a rooted device/emulator running.
- After injection, start Hodor's VPN inside the emulator and traffic — including Flutter apps — is decrypted with plaintext visible in the session list.
On API 34+ the runtime trust anchors live in a read-only APEX module
(/apex/com.android.conscrypt/cacerts); simply writing to /system is not
enough. HodorTrust handles this by bind-mounting a merged copy that includes
Hodor's CA. This overlay does not survive a reboot — re-run the injection after
restarting the device.
Troubleshooting
- App works but you see no plaintext / no sessions — the target host likely rejected Hodor's certificate, so Hodor forwards it untouched (this also keeps the app online). Use Path B to install the cert into the system store.
- Nothing is captured at all after toggling rules — confirm the Hodor VPN is actually connected, and that packet recording is enabled in the app.
- A Flutter app still not decrypting on a rooted device — verify you are on
the system certificate path (user certs never apply to
dart:io), and that the traffic is not certificate-pinned.
Ready to try it? Download Hodor for Android and the HodorTrust tool, or continue with the Capture Guide.