Charles Proxy CA Certificate on Genymotion via OpenSSL
To scrape a mobile app you first have to see what it sends. Most apps talk to a private HTTPS API, and the fastest way to discover those endpoints is to route the app's traffic through an intercepting proxy like Charles Proxy and read the decrypted requests and responses. The catch is TLS: to decrypt HTTPS, the proxy must present its own certificate, and the device has to trust that certificate's root CA. This guide shows how to generate a Charles Proxy CA certificate with OpenSSL on Windows and install it into a Genymotion Android virtual device — and, crucially, how to make it actually work on modern Android, which no longer trusts user-installed certificates the way it did in 2017.
Scope and ethics. Intercept only apps and accounts you're entitled to inspect, for interoperability, testing, or data you have a right to collect. Respect each service's terms and applicable law. This is a debugging and research technique, not a license to bypass protections you don't own.
Do you even need OpenSSL? (2026 reality check)
Here's the first modernization. In most cases you don't need to hand-roll a CA with OpenSSL anymore. Charles ships with its own root certificate and can generate and export it for you: Help → SSL Proxying → Install Charles Root Certificate (and the "on a Mobile Device or Remote Browser" variant). mitmproxy does the same at mitm.it. For everyday app inspection, using the proxy's built-in CA is simpler and less error-prone.
You'd generate your own CA with OpenSSL when you specifically want a custom root — a controlled certificate with your own subject/validity that you can reuse across tools and push into a device's system trust store. That's the scenario this guide covers, because it's also the scenario that teaches you how Android certificate trust really works. The steps below still apply to Charles's own exported CA — just skip to the installation section.
Step 1 — Get OpenSSL for Windows
Download an OpenSSL Windows build (Win64 for a 64-bit machine). Popular sources are the "Win32/Win64 OpenSSL" installers from Shining Light Productions, or the binaries bundled with Git for Windows (C:\Program Files\Git\usr\bin\openssl.exe). After installing to, say, C:\OpenSSL-Win64, you'll find openssl.exe in C:\OpenSSL-Win64\bin and the config at C:\OpenSSL-Win64\bin\openssl.cnf.
Step 2 — Generate the root CA certificate
Open a terminal in the bin folder and create a working directory for the CA, then generate a self-signed root certificate valid for ten years:
cd C:\OpenSSL-Win64\bin
mkdir CharlesCA
cd CharlesCA
openssl req -new -x509 -days 3650 -extensions v3_ca ^
-keyout ca_key.pem -out ca_cert.pem ^
-config ..\openssl.cnf
OpenSSL generates a private key, asks for a PEM passphrase (remember it — Charles will prompt for it later), and then collects the certificate's subject details:
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Interceptor CA
Organizational Unit Name (eg, section) []:Research
Common Name (e.g. server FQDN or YOUR name) []:Interceptor Root CA
Email Address []:you@example.com
You now have two files: ca_cert.pem (the public root certificate to install on clients) and ca_key.pem (the private key — keep it secret).
Step 3 — Convert to PKCS#12 for Charles
Charles expects the CA in PKCS#12 (.pfx/.p12) format, bundling the certificate and its key. Convert it:
openssl pkcs12 -export -out ca_cert.pfx -inkey ca_key.pem -in ca_cert.pem
Enter the key's passphrase, then set an export password (it can be empty). You now have ca_cert.pfx — the file you'll point Charles at.
Step 4 — Load the CA into Charles
In Charles: Proxy → SSL Proxying Settings → Client Certificates → Add, and select ca_cert.pfx. Charles will ask for the passphrase from Step 2. With SSL Proxying enabled and a location added (host *, port 443, to decrypt everything, or a specific host to stay targeted), Charles will now sign per-site certificates from your root — so any client that trusts your root can be decrypted.
Step 5 — Point Genymotion at Charles
Charles listens on port 8888 by default. Inside the running Genymotion virtual device, configure the Wi‑Fi to use your host machine as a manual proxy:
- Settings → Wi‑Fi, then long-press the connected network.
- Modify network → Advanced options.
- Set Proxy to Manual.
- Proxy hostname:
10.0.3.2— Genymotion's special alias for the host workstation (the equivalent of the AOSP emulator's10.0.2.2). - Proxy port:
8888. - Save.
Charles will pop a dialog asking to allow the new connection — accept it. HTTP traffic should now appear in Charles immediately. HTTPS won't decrypt yet — that's the certificate-trust step, and where modern Android changes everything.
Step 6 — Install and trust the CA on Android (the part that changed)
In 2017 you could drag ca_cert.pem into the device, install it as a user certificate (Settings → Security → Install from storage), and apps would trust it. That is no longer true. Since Android 7 (Nougat), apps do not trust user-added CA certificates by default. A certificate you install through Settings lands in the user store, which apps ignore unless their developer explicitly opted in. So a user-installed cert now only helps for the system browser and a handful of cooperative apps — not the typical app you're trying to inspect.
You have three real paths:
Option A — Install into the system trust store (rooted Genymotion)
This is the reliable route for app inspection, and Genymotion images are typically rooted, which makes it feasible. System CAs live in /system/etc/security/cacerts/, named by their subject hash with a .0 suffix.
First, compute the correct filename from your PEM (run on your host with OpenSSL):
openssl x509 -inform PEM -subject_hash_old -in ca_cert.pem | head -1
# -> e.g. 9a5ba575 -> filename must be 9a5ba575.0
Then push it into the system store over ADB (with the device running):
adb root
adb remount
adb push ca_cert.pem /sdcard/9a5ba575.0
adb shell "su -c 'mv /sdcard/9a5ba575.0 /system/etc/security/cacerts/ && \
chmod 644 /system/etc/security/cacerts/9a5ba575.0'"
adb reboot
On Android 10+ the /system partition may be read-only even for root; if remount fails, mount it writable first (adb shell "su -c 'mount -o rw,remount /system'") or use a Magisk-style system CA module. After a reboot the certificate appears under Settings → Security → Trusted credentials → System, and ordinary apps will trust your proxy.
Option B — Rebuild the app with a network security config
If you can rebuild or repackage the target app, add a Network Security Configuration that trusts user certificates for debug builds:
<!-- res/xml/network_security_config.xml -->
<network-security-config>
<base-config>
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</base-config>
</network-security-config>
Reference it from the manifest's <application android:networkSecurityConfig="@xml/network_security_config">. This makes a user-installed cert (Option A's easier cousin) trusted by that app. It only works for apps you can rebuild — your own, or one you decompile and repackage.
Option C — Use the system browser only
If you just need to inspect web traffic in Chrome/WebView browsing (not a native app's API), a user-installed certificate via Settings → Security → Encryption & credentials → Install a certificate → CA certificate is enough. Android will warn that the network may be monitored — expected.
When HTTPS still won't decrypt: certificate pinning
Even with your CA in the system store, some apps still refuse to connect or show SSL handshake errors in Charles. That's certificate pinning — the app ships a copy of the exact certificate/key it expects and rejects anything else, including your trusted root. Pinning is deliberate anti-interception, common in banking, streaming, and privacy-sensitive apps.
Defeating pinning means changing the app's runtime behavior, typically with Frida and a script such as objection's android sslpinning disable, or by patching the APK's pinning logic (or its Network Security Config <pin-set>) and resigning. These are advanced, app-specific techniques; pinning is a strong signal that the vendor doesn't want the traffic inspected, so weigh the ethics and terms before proceeding.
Modern alternatives to Charles
Charles remains popular, but the toolbox has grown:
- mitmproxy — free, open-source, scriptable in Python. Excellent for automated interception and for turning captured requests into a scraper, and
mitm.itserves its CA to devices. - Proxyman — a modern Charles-style GUI (macOS/Windows/iOS) with slick certificate installation helpers.
- Burp Suite — the security-testing standard, strong for deep request manipulation.
- PCAPdroid — on-device capture on Android without a separate proxy machine.
Any of these follows the same principle you just applied: the device must trust the proxy's root CA, and on modern Android that means the system trust store for app traffic.
Why this matters for scraping
Reverse-engineering an app's hidden API through an intercepting proxy is often the highest-leverage move in mobile data extraction. Once you can read the app's requests, you frequently discover clean JSON endpoints that are far more stable and efficient to collect from than scraping a rendered page — and understanding this traffic is also how you reason about anti-bot protection and when you'll need rotating proxies. If standing up this interception stack, defeating pinning, and maintaining it isn't where you want to spend your time, we do app and API reverse-engineering as part of a managed web scraping service.
Quick reference
- Generate a custom CA with
openssl req -new -x509, or just export Charles's own root — either works. - Convert to PKCS#12 (
ca_cert.pfx) and load it under Charles → SSL Proxying → Client Certificates. - Point Genymotion's Wi‑Fi proxy at
10.0.3.2:8888. - Android 7+ ignores user certs for apps — push the CA into
/system/etc/security/cacerts/on a rooted device (named bysubject_hash_old) for real app inspection. - If traffic still won't decrypt, suspect certificate pinning and reach for Frida/objection.