Charles Proxy Mac Setup: How Hackers Actually Read Your App’s Traffic

A few months back, a client asked me a simple question: “Is our delivery tracking app leaking anything it shouldn’t?” No pentest budget, no fancy lab, just a MacBook and an afternoon. That’s the kind of situation where Charles Proxy earns its keep. It’s not the flashiest tool in a security tester’s kit, but it’s usually the first one I open, because most app problems show up the moment you can actually see the traffic instead of guessing at it.

This guide walks through the same Charles Proxy Mac setup I use for that kind of work: installing it, getting HTTPS traffic to actually decrypt (which trips up almost everyone the first time), pointing an iPhone or Android device at it, and then what to actually look for once traffic starts flowing in.

What Charles Proxy Actually Does

Charles sits between your device and the internet as a local proxy. Every request your browser, phone, or app makes routes through it first, gets logged, and shows up in a readable structure: headers, body, response, timing, all of it. Think of it as a translator that intercepts a conversation between an app and its server and writes down every word.

For plain HTTP this works instantly. HTTPS is where it gets interesting, because the traffic is encrypted before it leaves the device. Charles handles this by acting as a man-in-the-middle: it issues its own certificate, your device is told to trust that certificate, and Charles decrypts, reads, then re-encrypts traffic on the way to the real server. This is exactly the same mechanism that makes SSL validation mistakes dangerous in production apps. If an app blindly trusts any certificate presented to it, Charles (or an attacker) can sit in the middle without much resistance.

Here’s what that man-in-the-middle process actually looks like step by step:

How Charles Proxy intercepts device-to-server HTTPS traffic

Once you understand that flow, the rest of this guide is really just “how do I get my device to trust step two.

Charles Proxy Mac Setup: Installing It the Right Way

Grab it from the official site: charlesproxy.com. The free trial runs indefinitely with a 30-minute-per-session limit (it restarts the recording, not the app), which is plenty for testing purposes.

Once it’s open:

  1. Charles will ask for permission to configure your Mac’s proxy settings. Allow it, this saves you a manual step later.
  2. Give it a minute to start capturing. Open Safari or Chrome and load any site; you should see requests populating under the Structure tab almost instantly.
  3. If nothing shows up, check Proxy β†’ macOS Proxy is ticked. On newer macOS versions (Sonoma and later), System Settings sometimes silently reverts the proxy entry after a network change, and a Wi-Fi toggle fixes it faster than digging through settings.

If Charles configured things correctly, your Mac’s proxy will point to 127.0.0.1:8888. You can confirm this manually under System Settings β†’ Network β†’ Wi-Fi β†’ Details β†’ Proxies.

Getting HTTPS to Actually Decrypt

This is the step that stalls most people, including me the first time I set this up years ago. Traffic shows up in Charles but every HTTPS row just says “Unknown” instead of readable JSON.

Here’s the fix, in order:

  1. Go to Help β†’ SSL Proxying β†’ Install Charles Root Certificate.
  2. Open Keychain Access, find the Charles Proxy certificate under System or login, double-click it, expand Trust, and set “When using this certificate” to Always Trust.
  3. Back in Charles, go to Proxy β†’ SSL Proxying Settings, enable SSL Proxying, and add *:443 (or specific domains like *.example.com:443 if you want to be selective, which is recommended once you’re comfortable, since intercepting everything gets noisy fast).

Restart the browser or app after this. If you skip the “Always Trust” step in Keychain, macOS will silently keep rejecting the certificate and you’ll see connection resets instead of any error message pointing at the actual cause, which is the part that wastes the most time when you’re new to this.

If the Keychain steps above feel abstract on the page, this walkthrough shows the exact clicks in real time, from certificate install to the first decrypted request.

Once that’s working locally, the next step is pointing an actual phone at it, which is where most of the real setup friction shows up.

Here’s the same four steps laid out visually, since this is the part where most setups quietly break:

Four-step HTTPS decryption setup flow on Mac

Step 2 is the one to double-check if traffic still shows up encrypted after everything else looks right.

Setting Up iOS and Android Devices

For a phone on the same Wi-Fi network as your Mac:

iOS:

  • Note your Mac’s local IP (Charles shows this under Help β†’ Local IP Address).
  • On the iPhone: Settings β†’ Wi-Fi β†’ (i) next to your network β†’ Configure Proxy β†’ Manual, enter the Mac’s IP and port 8888.
  • Visit chls.pro/ssl in Safari on the phone to download the certificate, then install it under Settings β†’ General β†’ VPN & Device Management.
  • One step people forget: even after installing, you need to go to Settings β†’ General β†’ About β†’ Certificate Trust Settings and manually enable full trust for the Charles certificate. Without this, the cert installs but does nothing.

Install and trust are genuinely two different phases on iOS. Here’s why that trips people up:

iOS certificate install versus trust process for Charles Proxy

Android has a similar two-part logic, minus the extra Certificate Trust Settings screen β€” the CA install itself is usually the only step people miss there.

Android:

  • Same manual proxy setup under Wi-Fi settings.
  • Download and install the certificate as a CA cert (Settings β†’ Security β†’ Encryption & Credentials β†’ Install a certificate).
  • From Android 7 onward, apps that target a recent SDK version ignore user-installed CA certificates by default unless the app’s network security config explicitly allows it. This is why plenty of banking and fintech apps simply refuse to show any traffic in Charles no matter how correctly you’ve set things up. It’s not a Charles problem, it’s the app deliberately locking that door.

That last point matters more than most tutorials mention. If you’re testing an app and see zero traffic despite a correct setup, don’t assume you misconfigured something. Check whether the app pins its certificate or restricts trust anchors first.

What I Actually Look For Once Traffic Is Flowing

Setup is the boring half. The useful part is reading what comes through:

  • Authentication headers: is a bearer token or session ID sitting in a header that’s identical across every request? That’s often a sign of weak session handling.
  • Login and password reset flows: worth checking whether reset tokens ever leak into a URL instead of staying in the request body, which ties directly into the kind of exposure covered in password reset tokens in URLs.
  • Response bodies on failed logins: apps that return different error messages for “wrong password” versus “user doesn’t exist” are handing out a free username enumeration tool.
  • Endpoints that shouldn’t be reachable: sometimes an app calls an internal or admin-facing endpoint that has no business being in a consumer build.

On one job, this exact workflow surfaced a JWT token with an absurdly long expiry sitting in plain view in a request header, on an app that had no refresh-token rotation at all. Nothing exotic, just a plain proxy and five minutes of watching traffic scroll by.

When Apps Fight Back: SSL Pinning

Plenty of apps won’t show a thing in Charles even with a perfectly correct setup, because they check the server’s certificate against a hardcoded value rather than trusting the device’s certificate store. This is certificate pinning, and it’s a deliberate defense against exactly this kind of interception.

Bypassing pinning for legitimate, authorized testing usually means instrumenting the app at runtime rather than fighting Charles harder. This is where tools like Frida hooking come in β€” you hook the pinning check itself and force it to return true, which is a deeper rabbit hole than Charles setup, and worth understanding separately if you’re doing this kind of testing regularly; the comparison between Frida and Xposed is a reasonable next read once you’re past the basics covered here.

It’s also worth knowing that some apps ship Runtime Application Self-Protection to detect and shut down exactly this kind of tampering. See how RASP tooling works if traffic capture keeps mysteriously failing on a specific app even after a pinning bypass.

Rewriting Requests and Setting Breakpoints

Charles isn’t just a passive logger. Two features are worth knowing early:

  • Breakpoints (Proxy β†’ Breakpoint Settings) pause a request before it reaches the server, letting you edit parameters live. Useful for testing what happens if you change a role field or a quantity value before it’s sent.
  • Map Local / Rewrite lets you substitute a different response entirely, which is handy for testing how an app’s frontend handles unexpected or malformed server responses without needing backend access at all.

Both are more about testing app resilience than plain traffic reading, but once you’re comfortable with the basics they turn Charles from an observation tool into something closer to a lightweight manual fuzzer.

Doing This Legally

Everything above assumes you’re testing an app you own, or one you have explicit written authorization to test. Intercepting traffic on an app or network you don’t have permission for isn’t a gray area, it’s unauthorized access, plain and simple, the same category of risk discussed around enterprise Wi-Fi exploitation. If you’re reporting a finding to a vendor afterward, it’s worth understanding how information should be shared responsibly. The Traffic Light Protocol is the standard most security teams expect you to follow when disclosing what you found.

Common Setup Problems

ProblemLikely CauseFix
“Unknown” traffic despite SSL Proxying onCertificate not set to Always TrustRecheck Keychain Access trust setting
No traffic from phone at allPhone on cellular, not same Wi-FiConnect both devices to same network
App crashes after proxy setApp detects proxy, anti-tampering checkNot a Charles bug, app-level defense
Certificate installed but iOS still not decryptingTrust toggle not enabled separatelyEnable in Certificate Trust Settings

Charles vs Burp Suite vs Wireshark

ToolBest forSetup difficultyIdeal use case
Charles ProxyQuick traffic inspectionEasyFirst look at any app's API calls
Burp SuiteDeep API pentestingModerate–HardIntruder, repeater, full vulnerability scan
WiresharkRaw packet-level analysisHardDebugging below HTTP (TCP handshake issues)

My usual order: Charles first for a quick look, Burp if the app turns out to have something worth digging into properly.

Frequently Asked Questions

Do I need a paid Charles Proxy license for this?

No. The free trial has no feature restrictions. It just re-limits your recording session every 30 minutes, which resets automatically and doesn’t stop the proxy from working.

Why does Charles show HTTPS traffic as garbled text instead of JSON?

SSL Proxying isn’t fully enabled for that domain, or the root certificate isn’t set to Always Trust in Keychain Access. Both steps are required together.

Can Charles Proxy see traffic from apps with certificate pinning?

Not without additional work. Pinned apps reject Charles’s certificate outright. You’d need runtime instrumentation (like Frida) to bypass the pinning check first.

Is it legal to intercept my own app’s traffic?

Yes, testing traffic on an app you own or have written authorization to test is standard practice in security testing and app debugging. Testing third-party apps without permission is not.

What’s the biggest mistake beginners make with Charles Proxy on Mac?

Assuming installing the certificate is enough. On both Mac and iOS, you have to separately mark that certificate as fully trusted β€” installation and trust are two different steps, and skipping the second one is responsible for most “it’s just not working” reports.

Scroll to Top