User manual

Charlotte is an HTTPS debugging proxy: point an app or device at it, and you can read, change and replay every request it makes — including encrypted ones. This manual covers both apps; pick yours and the steps adapt.

1. Get started

macOSInstall Charlotte from the Mac App Store. It runs on macOS 26 or later.

New in 2.3: Charlotte 2.3 for macOS is out now. It adds governance and an MCP gateway, Assert regression tests from captured traffic, Share Live and Git for HTTP on the command line — see What's New on the Mac App Store page.

WindowsInstall Charlotte from the Microsoft Store. It runs on 64-bit Windows 10 and 11 (x64 and Arm64). The Store install also puts a charlotte command on your PATH.

On first launch the Setup Guide walks you through three things, in order. Reopen it at any time from Help → Charlotte Setup Guide (⌘?)the Setup Guide button in the toolbar.

  1. Create a root certificate — Charlotte's own certificate authority, used to decrypt HTTPS (section 2).
  2. Trust it on the machine or device you want to inspect.
  3. Send traffic through Charlotte — this computer, a phone, a simulator or an emulator (section 3).

The proxy listens on port 8888 by default. Change it in Settings → Proxy listener if another tool (Charles and Fiddler also default to 8888) already uses it.

Capturing and inspecting traffic is free. Charlotte Pro unlocks Tools (Map Remote, Map Local, Rewrite, Mocks), Breakpoints, Throttling, the MCP server and on-device AI. Manage it in Settings → License.

2. The root certificate

HTTPS can't be read off the wire. Charlotte completes the encrypted connection itself and presents each app a certificate for the site it asked for, signed by a root certificate authority that only you have. Once a device trusts that root, Charlotte can decrypt that device's traffic. The private key never leaves your computer.

Create it

Settings → Root Certificate Authority → GenerateGenerate a new Charlotte root CA. Charlotte saves it and reuses it on every launch. Generating again replaces it, and devices that trusted the old one will need the new one. You can also import an existing CA as a .p12/.pfx file.

Trust it on this computer

macOSClick Trust on this Mac…. Charlotte exports the certificate and opens it in Keychain Access. Add it to your login keychain, open it, expand Trust, and set When using this certificate to Always Trust. Settings shows Trusted on this Mac when that worked; click Re-check certificate trust if it doesn't update.

WindowsClick Trust it in Windows…. Windows' own certificate import wizard opens; finish it to add the certificate to your user's Trusted Root Certification Authorities. Charlotte never installs certificates by itself — Windows asks you to confirm. Remove from my trusted roots undoes it.

Only trust a Charlotte root on devices you own or are authorised to test, and remove it when you're done (in Keychain Access, delete the certificateSettings → Remove from my trusted roots, or Undo Charlotte's changes to Windows; on phones, delete the profile).

3. Capture traffic

Start the proxy with Start Proxy (⌘R). Then point something at it. Device Setup in the toolbar has a panel for each kind of client.

This computer

macOSIn Device Setup, turn on Capture this Mac's traffic. It sets the Mac's Web (HTTP) and Secure Web (HTTPS) proxies to 127.0.0.1:8888. The App Store build isn't allowed to change network settings itself, so there the switch opens System Settings → Network → your connection → Details → Proxies, where you set both proxies by hand. Turn them off when you finish, or apps lose their connection once Charlotte quits. Turning the switch off puts back what was there before — including a company PAC script or automatic proxy discovery, which Charlotte pauses while it captures.

WindowsTurn on Windows user proxy in the toolbar. It points your Windows user's proxy — the one browsers, .NET, WinHTTP-based apps and most desktop software use — at Charlotte, and turning it off restores what was there before. Apps that ignore the system proxy need it set in the app itself (see below).

Command-line tools and SDKs

Most tools honour the standard environment variables. Make the tool trust the exported certificate too (Settings → Export Root Certificate (.pem)…Export root certificate (.cer)…):

export HTTPS_PROXY=http://127.0.0.1:8888 HTTP_PROXY=http://127.0.0.1:8888
curl --cacert ~/Downloads/charlotte-ca.pem https://api.example.com/
# Node:   NODE_EXTRA_CA_CERTS=~/Downloads/charlotte-ca.pem
# Python: REQUESTS_CA_BUNDLE=~/Downloads/charlotte-ca.pem
$env:HTTPS_PROXY = "http://127.0.0.1:8888"; $env:HTTP_PROXY = "http://127.0.0.1:8888"
curl.exe --proxy http://127.0.0.1:8888 https://api.example.com/
# Node:   $env:NODE_EXTRA_CA_CERTS = "$HOME\Downloads\charlotte-ca.pem"

iPhone and iPad

  1. Join the same Wi-Fi as the computer running Charlotte. On Windows, also turn on Settings → Accept connections from other devices on the network, and allow Charlotte through Windows Firewall when asked.
  2. Settings → Wi-Fi → ⓘ → Configure Proxy → Manual. Server: your computer's address (Device Setup shows it). Port: 8888.
  3. In Safari, open http://charlotte.proxy — or scan the QR code in Device Setup — and tap Install profile.
  4. Settings → General → VPN & Device Management → install the profile.
  5. Settings → General → About → Certificate Trust Settings → turn on full trust for the Charlotte root.

Android

Set the device's or emulator's Wi-Fi proxy to your computer's address and port 8888, then open http://charlotte.proxy to download the certificate. Since Android 7, apps trust user-installed certificates only if they opt in, so for your own app add a network_security_config that trusts user certificates in debug builds. For a rooted or debuggable emulator (for example a non–Google Play image), Device Setup's Trust CA installs the certificate into the system store over adb. On Windows, the toolbar's Android simulators switch routes every running emulator through Charlotte.

iOS Simulator

macOSSimulators share the Mac's network, so the Mac's proxy applies. In Device Setup, Trust Charlotte CA in booted Simulators installs the root into every running simulator; restart the app under test afterwards.

Several devices at once

Every flow records the address it came from. When devices share one address (behind NAT), give each its own capture port in Settings; flows arriving on that port carry the device's name.

4. Read and filter flows

Each request and its response is a flow. Select one to see its tabs:

TabWhat it shows
OverviewURL, status, protocol (HTTP/1.1 or HTTP/2), TLS version and ALPN, server address, timings (connect, time to first byte, total) and sizes — plus Windows-authentication and HTTP/3 diagnostics when they apply.
Request / ResponseHeaders and body. Bodies are decompressed (gzip, deflate, brotli, zstd) and shown as a JSON tree, HTML, XML, images, Protobuf/gRPC, hex and more. Streaming responses (Server-Sent Events) fill in live.
MessagesWebSocket frames in both directions.
ContractResults of checking the flow against an attached OpenAPI description (section 8).

Right-click a flow for Copy URL, Copy as cURL, Create mock from response, Edit & replay, Save to collection, Explain with AI (Pro), or to focus its host.

The filter

Type into the filter bar (⌘K). Plain words search the method, URL, headers and bodies. Fields narrow it down; terms combine with AND unless you write OR:

ExampleMatches
status:>=400errors (also status:200-299)
host:*.api.example.com path:/v1/*wildcard host and path
method:POST type:jsonJSON POSTs
header:authorization, body:"user_id"a header name, text in a body
duration:>500 size:>1000slow or large flows
is:error is:streaming is:websocketflow kinds
openapi:failcontract violations
(host:a.com OR host:b.com) -method:GETgrouping and negation

Save filters you reuse from the filter menu. To cut noise, right-click a row and focus its host, or use Settings → Recording filter so Charlotte doesn't record unwanted hosts at all (their traffic still flows).

5. Choose what to decrypt

Settings → SSL Proxying controls which HTTPS hosts Charlotte opens up:

  • Include hosts — if set, only these are decrypted. Empty means everything.
  • Exclude hosts — never decrypted. Charlotte passes these connections through untouched (a blind tunnel): they work normally but show no content.

Use *.example.com wildcards. Exclude a host when its app pins its certificate (it refuses Charlotte's and fails), or when a server rejects decrypted sign-ins (section 10). Charlotte always passes the operating system's own pinned services through — iCloud, Apple Push and App Store hostsWindows Update, licensing and Store hosts — so they keep working and stay out of your capture.

HTTP/3

Charlotte can't decrypt HTTP/3, which runs over UDP (QUIC). Flows from hosts that offer it are tagged H3. Turn on Settings → Upstream → Force HTTP/2 fallback to strip the Alt-Svc advertisement so clients stay on HTTP/2 or HTTP/1.1, then restart the client.

6. Tools and breakpoints Pro

Open Tools in the toolbar. Rules match on scheme, host, port and path (wildcards allowed) and apply live.

ToolUse it to
Map RemoteSend matching requests to a different server, e.g. production → staging.
Map LocalAnswer from a file on disk instead of the network.
RewriteAdd, change or remove headers, query parameters, status codes and body text.
MocksServe a recorded or templated response. Right-click a flow → Create mock from response. Templates can use {{…}} placeholders.
BreakpointsPause matching requests or responses, edit them, then continue or abort.

Throttling (Settings) adds latency, caps bandwidth and drops a share of connections, to test slow or flaky networks. Restart the proxy after changing it.

7. Compose and replay

Compose builds a request from scratch, or from a captured one with Edit & replay, and sends it through Charlotte so the result is captured like any other flow. Collections keep requests for reuse, with {{variables}} you can switch per environment, and can be exported and shared.

8. gRPC, Protobuf and OpenAPI

Protobuf and gRPC

Protobuf and gRPC bodies are decoded as raw fields automatically. To see field names, load a schema: import .proto files or a folder, or fetch it from a server that supports gRPC server reflection — over plaintext, TLS (custom trust roots and server-name override) or mTLS (a PKCS#12 or PEM identity), with metadata and a timeout.

OpenAPI verification

Click Attach OpenAPI Description… and choose an OpenAPI 3.0 or 3.1 file (YAML or JSON). Every captured request and response is checked: operation, parameters, security, bodies, status codes and headers. Results appear in the flow's Contract tab, as a badge in the list, and through the openapi:pass|fail|undocumented|skipped filter terms. Formats sets whether format keywords (email, uuid…) are ignored, warned about or enforced.

9. Sessions and exports

  • Save Session… / Open Session… (⌘S / ⌘O) — Charlotte's own .charlottesession format, identical on macOS and Windows: a session saved on one opens on the other.
  • Export as HAR… / Import HAR… — to and from browsers' developer tools and other proxies.
  • Copy as cURL on any flow (also as PowerShell curl and Invoke-RestMethod).
  • Audit reviews the session on your computer for security and privacy issues — secrets in URLs, cookies without security flags, plaintext credentials — and redacts the secrets it reports.

10. Active Directory, Kerberos and NTLM

Company intranet sites, SharePoint, IIS and many internal APIs sign users in with Windows Integrated Authentication: the Negotiate scheme (Kerberos, falling back to NTLM) or NTLM. Both differ from other web sign-ins in two ways that matter to a proxy:

  • They sign in a connection, not a request. NTLM is a three-step handshake that must stay on one connection, and the server remembers the signed-in user for that connection.
  • They may be tied to the server's certificate. With Extended Protection for Authentication (EPA, also called channel binding) the client mixes the server's certificate into its ticket. Through a decrypting proxy the client sees Charlotte's certificate instead, so the server refuses the ticket — even though the account is fine.

The automatic handling, the diagnosis, Sign in for these hosts and Sign in as described here arrive in Charlotte 2.2. On earlier versions, add the sign-in host to SSL Proxying → Exclude hosts.

What Charlotte does automatically

As soon as a request or response shows an NTLM or Negotiate handshake, Charlotte keeps that client's connection paired with its own connection to the server. The handshake completes, and the signed-in identity is never shared with another app or device. Hosts that use Windows authentication are served over HTTP/1.1, because the handshake can't run over HTTP/2 (servers answer HTTP_1_1_REQUIRED, and Charlotte does the same to clients, which then retry over HTTP/1.1). There's nothing to configure.

Reading the diagnosis

Flows that are part of a Windows sign-in get a Windows authentication block in their Overview:

It saysMeaning
Server requires Windows authenticationThe normal first challenge. The client answers next.
… handshake in progressNTLM's middle step. Expected.
… acceptedSigned in.
… rejectedThe server refused a complete Kerberos ticket or NTLM response. Over HTTPS this almost always means Extended Protection (below). Over plain HTTP, check the account, the clock (Kerberos tolerates five minutes of difference) and the server's service principal name (HTTP/host).

Servers with Extended Protection

No proxy can make a client's own ticket valid for a certificate the client never saw. There are two ways through, and a rejected flow offers both as buttons:

  1. Let Charlotte sign in for you — Settings → Windows authentication → Sign in for these hosts. For those hosts Charlotte answers the server's challenge itself, with the Kerberos ticket this Mac already has (from signing in to the domain, the Kerberos SSO extension, or kinit)your Windows account, using Kerberos or NTLM exactly as Windows itself would — or the account under Sign in as (below) — bound to the server's real certificate. You still see every request and response decrypted.
  2. Don't decrypt the host — add it to SSL Proxying → Exclude hosts. Sign-in works because the client talks to the real server, but that host's traffic is no longer readable. Choose this for sign-in servers you don't need to read, such as AD FS or login.microsoftonline.com.

Restart the proxy after changing either list.

macOSWith your own ticket Charlotte signs in with Kerberos. A server that offers only NTLM needs an account under Sign in as; without one, Charlotte leaves the handshake to your app, which works through Charlotte unless the server also enforces Extended Protection.

To check you have a ticket, run klist in Terminal. No ticket? Sign in with the Kerberos SSO extension or Ticket Viewer, or run kinit you@CORP.EXAMPLE.COM.

WindowsCharlotte signs in as the Windows user it runs as, through the same system component (SSPI) that Edge and Office use. On a domain-joined PC that means Kerberos, with NTLM as the fallback.

Sign in as another account

Settings → Windows authentication → Sign in as takes an account — CORP\alice or alice@corp.example.com — and its password. Charlotte then uses it for Sign in for these hosts and for your company's proxy (section 11), with Kerberos when a domain controller can be reached and NTLM otherwise. Leave it blank to use your own Kerberos ticketyour own Windows account; then nothing is stored.

  • The password is kept in your login Keychainencrypted with your Windows account (DPAPI), never in plain settings.
  • Charlotte's ticket for the account lives in its own memory. It never appears in klist and never changes which identity the rest of the Mac uses.
  • Everyone whose traffic goes through Charlotte to a Sign in for these hosts entry reaches it as this account, so use it on your own computer, not on a shared capture box.
  • For a NetBIOS name such as CORP\alice, Kerberos uses the default realm in your Kerberos configurationthe domain Windows finds for it; if you have none, use the alice@corp.example.com form.the alice@corp.example.com form always works.

Apps that sign in to Microsoft Entra ID (Azure AD)

Apps built on Microsoft's sign-in libraries (MSAL, Authenticator, Company Portal, Intune) often pin certificates or rely on device attestation. If their sign-in fails only through Charlotte, exclude login.microsoftonline.com, *.microsoftonline.com, login.windows.net and your AD FS host, and keep decrypting your own API hosts.

11. Your company's proxy

On many company networks nothing reaches the internet except through the company's proxy. Charlotte normally connects to servers directly, so on such a network it needs to know about that proxy too: Settings → Upstream proxy → Connect through.

ChoiceUse it when
None — connect directlyYou're at home, or your network has no proxy. The default.
Use the system's proxyAlmost always the right choice at work. Charlotte uses the PAC script, automatic discovery (WPAD) or proxy that macOSWindows had before Charlotte became the system proxy, so capturing this computer doesn't cut Charlotte off from the network.
ManualYour IT department gave you a proxy address such as proxy.corp.example.com:8080. List hosts to reach directly under Go direct to: *.corp.example.com, 10.*, 10.0.0.0/8, or <local> for names without a dot.
Automatic configuration script (PAC)You were given a PAC URL, such as http://wpad.corp.example.com/proxy.pac.

Everything Charlotte sends goes this way: decrypted traffic, hosts it doesn't decrypt, WebSockets, and the requests you make yourself in the Composer and with replays, and gRPC reflection. Charlotte never chains into itself: if the system's settings point at Charlotte, it skips to the next proxy, or goes direct.

Proxies that ask you to sign in

When the proxy answers 407 Proxy Authentication Required, Charlotte signs in to it — with Kerberos as your own ticketyour Windows account, or as the Sign in as account (section 10) with Kerberos, NTLM or a user name and password (Basic). Your apps never see the proxy's challenge. If the proxy refuses, the request fails with a 502 whose text names the proxy, the account and what it offered — the quickest way to tell a wrong password from a proxy that wants something else.

Restart the proxy after changing these settings.

12. AI agents (MCP) Pro

Charlotte can share captured traffic with AI agents over the Model Context Protocol. Turn it on in Settings → AI / MCP server. It listens on http://127.0.0.1:8765/ only — never on the network — and requires the access token shown there. For agents that launch a command instead, use charlotte --mcp-stdio. The MCP Setup Guide… writes the configuration for common clients. Agents can list and search flows and follow new ones live; they can add rules and replay requests only if you allow it. Secrets are hidden from agents unless you turn that off. More on the MCP page.

13. Command line and CI

macOSThe command lives inside the app bundle. Charlotte --shell-setup prints a line to add to your ~/.zshrc:

alias charlotte='/Applications/Charlotte.app/Contents/MacOS/Charlotte'

WindowsThe Store install puts charlotte on your PATH for PowerShell and cmd.

CommandDoes
charlotte --headless --port 8888Capture without the window; stop with Ctrl+C.
charlotte --headless --upstream-proxy systemChain through your company's proxy for this run: direct, system, pac=URL or host:port (section 11). Settings aren't changed.
charlotte --headless --sign-in-hosts intranet.corp.example --sign-in-as CORP\aliceSign in to those hosts for this run, as that account. The password comes from the CHARLOTTE_SIGN_IN_PASSWORD environment variable (section 10).
charlotte --status --jsonState of the running app or headless instance.
charlotte --export-live --format har --output capture.harSave what's captured so far.
charlotte --assert capture.har --no-secrets --fail-if "status:>=500" --report junit --output results.xmlFail a CI job on errors, leaked secrets or slow endpoints (--p95-query, --p95-max-ms).
charlotte --probeDiagnose a running Charlotte: is the port open, is it Charlotte, is it decrypting.
charlotte --ca-export charlotte-ca.pemExport the root certificate.

14. Troubleshooting

Nothing appears in the list

Check the proxy is running and the client really uses it: run charlotte --probe. On a phone, re-check the Wi-Fi proxy address and port, and that both devices are on the same network and Windows Firewall allows Charlotte. Some apps ignore the system proxy; set it in the app or with environment variables.

HTTPS requests fail, or show only "CONNECT"

The client doesn't trust Charlotte's root. Repeat section 2 on that device — on iOS, the separate Certificate Trust Settings switch is the step most often missed. Apps that pin certificates never accept it: add their hosts to Exclude hosts.

One app works, another doesn't

Usually certificate pinning, HTTP/3, or Windows authentication. Some system services are always passed through untouched, so an app that talks mainly to iCloudMicrosoft's own services keeps working even though Charlotte never decrypts that part of its traffic. For intranet apps that sign in with Active Directory, see section 10; on a network with its own proxy, section 11.

Intranet or SharePoint sign-in loops or fails

Open the failing flow's Overview. Rejected over HTTPS means Extended Protection: use Let Charlotte sign in or Don't decrypt (section 10). A browser that keeps asking for a password usually doesn't consider the site part of the intranet, so it won't sign in automatically — that's a browser or policy setting, not Charlotte.

At work, nothing loads once Charlotte is the system proxy

Your network needs its own proxy, and Charlotte is going direct. Set Settings → Upstream proxy → Connect through to Use the system's proxy and restart the proxy (section 11). If requests now fail with a 502 that mentions the upstream proxy, its text says why — usually an account to set under Sign in as.

"Port 8888 is already in use"

Another proxy is running (Charles and Fiddler use 8888 too). Quit it, or choose another port in Settings and update your clients.

The site works in the browser but not in my app

Compare the two flows' request headers — user agent, cookies, authorization. Copy as cURL lets you replay the app's exact request from a terminal.

Still stuck? Contact support with your Charlotte version, operating system and what you were trying to capture. A saved session of the failing flows helps most.