Charles Proxy

How to use Charles Proxy in 2026 [Complete Guide]

Charles Proxy is an HTTP debugging proxy that captures and decrypts network traffic between your device and the internet. This guide covers installation, SSL configuration, advanced debugging techniques, and hidden tricks that most tutorials miss.

Whether you're debugging APIs, reverse engineering mobile apps, or testing network conditions, you'll find practical examples and ready-to-use scripts here.

What is Charles Proxy?

Charles Proxy works as a man-in-the-middle between your applications and remote servers. It intercepts HTTP and HTTPS traffic, letting you inspect requests, modify responses, and simulate various network conditions.

Unlike browser DevTools, Charles captures traffic from any application on your system. This includes mobile apps, desktop software, command-line tools, and background services.

The tool runs locally on your machine and creates a proxy server (default port 8888). Applications route traffic through this proxy, giving you complete visibility into the network layer.

Installing Charles Proxy

Head to the official Charles Proxy website and download the installer for your operating system. The tool supports macOS, Windows, and Linux.

macOS Installation:

# Using Homebrew
brew install --cask charles

# Or download directly from charlesproxy.com

Windows Installation:

Download the .msi installer and run it. Charles 5 now offers both .appx and .msi packages. The .appx version integrates better with Windows Store apps.

Linux Installation:

# Add Charles repository
wget -q -O - https://www.charlesproxy.com/packages/apt/PublicKey | sudo apt-key add -
sudo sh -c 'echo deb https://www.charlesproxy.com/packages/apt/ charles-proxy main > /etc/apt/sources.list.d/charles.list'

# Install
sudo apt-get update
sudo apt-get install charles-proxy

After installation, launch Charles. On first run, it asks permission to configure system proxy settings automatically. Grant this permission to start capturing traffic immediately.

Configuring SSL Proxying

HTTPS traffic appears encrypted by default. To inspect it, you need to enable SSL proxying and install the Charles root certificate.

Step 1: Enable SSL Proxying

Navigate to Proxy > SSL Proxying Settings. Check "Enable SSL Proxying" and add the domains you want to decrypt.

Use *:* to proxy all HTTPS traffic. For targeted debugging, add specific domains like api.example.com:443.

Step 2: Install Root Certificate

On macOS:

Help > SSL Proxying > Install Charles Root Certificate

This opens Keychain Access. Find the Charles Proxy CA certificate, double-click it, expand Trust, and set "When using this certificate" to "Always Trust".

On Windows:

Help > SSL Proxying > Install Charles Root Certificate

Follow the wizard to install the certificate in the Trusted Root Certification Authorities store.

On iOS devices:

  1. Connect your device to the same WiFi network
  2. Set the HTTP proxy to your computer's IP and port 8888
  3. Open Safari and navigate to chls.pro/ssl
  4. Download and install the profile
  5. Go to Settings > General > About > Certificate Trust Settings
  6. Enable full trust for Charles Proxy CA

On Android devices:

# For Android 7+, you need to add network security config
# Add to AndroidManifest.xml:
# android:networkSecurityConfig="@xml/network_security_config"

Create res/xml/network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <debug-overrides>
        <trust-anchors>
            <certificates src="user" />
        </trust-anchors>
    </debug-overrides>
</network-security-config>

For system-level certificate installation on Android emulators:

# Get certificate hash
openssl x509 -inform PEM -subject_hash_old -in charles-ssl-proxying-certificate.pem | head -1
# Output: 4fe145fd

# Rename certificate
mv charles-ssl-proxying-certificate.pem 4fe145fd.0

# Push to emulator (requires root)
adb root
adb remount
adb push 4fe145fd.0 /system/etc/security/cacerts/
adb shell chmod 644 /system/etc/security/cacerts/4fe145fd.0
adb reboot

Inspecting HTTP Traffic

Once SSL proxying is configured, Charles displays all network traffic in two views.

Structure View organizes requests by domain in a tree hierarchy. Expand any domain to see individual endpoints and resources.

Sequence View shows requests chronologically with timing information. This helps identify slow requests and understand request order.

Click any request to see details in the bottom panel:

  • Overview: URL, method, status, timing
  • Request: Headers, query parameters, body
  • Response: Status, headers, body content
  • Timing: DNS, connect, SSL handshake, request, response phases

For JSON responses, Charles automatically formats and syntax-highlights the content. You can search within responses using Cmd+F (Mac) or Ctrl+F (Windows).

Using Breakpoints for Live Debugging

Breakpoints pause requests or responses mid-flight. This lets you inspect and modify data before it reaches its destination.

Setting a Breakpoint:

Right-click any request and select Breakpoints. Charles pauses execution whenever a matching request occurs.

You can also configure breakpoints globally via Proxy > Breakpoint Settings. Add URL patterns and choose whether to break on request, response, or both.

Practical Example: Testing Authentication Edge Cases

Suppose you're debugging a login flow. Set a breakpoint on the login endpoint:

  1. Right-click the login request
  2. Select Breakpoints
  3. Attempt login in your app
  4. Charles pauses the request
  5. Modify the payload (e.g., change password)
  6. Click "Execute" to continue

You can also modify responses to test how your app handles different states:

// Original response
{
  "user": "alice",
  "role": "user"
}

// Modified response (test admin access)
{
  "user": "alice",
  "role": "admin"
}

This technique helps QA teams verify authorization logic without backend changes.

Rewrite Rules for Automated Modifications

Breakpoints require manual intervention. For automated modifications, use Rewrite rules.

Navigate to Tools > Rewrite and enable the feature. Create rule sets that automatically modify requests or responses based on patterns.

Common Rewrite Use Cases:

1. Redirect API Endpoints

Type: Host
Match: api.production.com
Replace: api.staging.com

2. Add Custom Headers

Type: Add Header
Match: Host = api.example.com
Header Name: X-Debug-Mode
Header Value: true

3. Modify Response Body

Type: Body
Match: URL = */api/config
Find: "feature_enabled": false
Replace: "feature_enabled": true

4. Change Status Codes

Type: Response Status
Match: URL = */api/user
Value: 500

This last example helps test error handling without waiting for actual server failures.

Map Local: Serve Files from Your Machine

Map Local overrides remote resources with local files. This is incredibly useful for frontend development.

Navigate to Tools > Map Local and add mappings.

Example: Override a JavaScript File

Remote URL: https://example.com/js/app.bundle.js
Local Path: /Users/you/project/dist/app.bundle.js

Now every request for the production bundle serves your local development version instead. You can test code changes against production data without deploying.

Example: Mock API Responses

Create a local JSON file:

// /Users/you/mocks/users.json
{
  "users": [
    {"id": 1, "name": "Test User", "email": "test@example.com"}
  ]
}

Map the API endpoint:

Remote URL: https://api.example.com/users
Local Path: /Users/you/mocks/users.json

Your app now receives mocked data. This speeds up frontend development when backend APIs aren't ready.

Map Remote: Redirect Traffic Between Environments

Map Remote redirects requests to different servers. Unlike Map Local, the response still comes from a server—just a different one.

Navigate to Tools > Map Remote.

Example: Test Against Staging

Map From: https://api.production.com/
Map To: https://api.staging.com/

All production API calls now hit staging. Your production-configured app tests against staging data.

Example: Route Specific Endpoints

Map From: https://api.example.com/v2/
Map To: https://api.example.com/v3/

Test v3 API compatibility without changing your app's configuration.

Network Throttling: Simulate Real-World Conditions

Most apps work fine on fast connections. Real-world users often have slower, unreliable networks.

Navigate to Proxy > Throttle Settings to configure bandwidth limits and latency.

Built-in Presets:

  • 56 kbps Modem
  • 256 kbps ISDN
  • 3G
  • 4G
  • DSL

Custom Configuration:

For more control, set individual parameters:

Bandwidth: 256 kbps (download) / 128 kbps (upload)
Utilisation: 80%
Round-trip Latency: 300 ms
MTU: 1500 bytes
Reliability: 95%
Stability: 90%

The Reliability setting simulates packet loss. Set it to 90% to drop 10% of packets, revealing timeout handling issues.

Throttling Specific Hosts:

Check "Only for selected hosts" and add domains. This throttles specific APIs while keeping other traffic fast—useful when you need to download documentation while testing slow conditions.

Enable throttling with Proxy > Start Throttling or press Cmd+T (Mac) / Ctrl+T (Windows).

Reverse Engineering APIs with Charles Proxy

Modern web apps and mobile apps communicate via APIs that aren't publicly documented. Charles Proxy helps discover and understand these hidden endpoints.

Step 1: Capture Traffic

Open Charles and enable SSL proxying for the target domain. Use the app normally, triggering the features you want to understand.

Step 2: Analyze Requests

Filter traffic to the target domain. Look for patterns:

  • Authentication headers (Bearer tokens, API keys)
  • Session cookies
  • Request payloads
  • Pagination parameters
  • GraphQL queries

Step 3: Export and Replicate

Right-click any request and select Copy cURL Request. This generates a command you can run in terminal:

curl 'https://api.example.com/data' \
  -H 'Authorization: Bearer eyJ...' \
  -H 'Content-Type: application/json' \
  --data-raw '{"query":"products","limit":20}'

Use this curl command to test modifications. Once you understand the API, replicate it in your scraping code.

Python Example:

import requests

headers = {
    'Authorization': 'Bearer eyJ...',
    'Content-Type': 'application/json',
    'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X)'
}

payload = {
    'query': 'products',
    'limit': 20,
    'cursor': None
}

response = requests.post(
    'https://api.example.com/data',
    headers=headers,
    json=payload
)

data = response.json()
print(data)

This approach bypasses complex JavaScript rendering. Direct API calls are faster and more reliable than headless browsers.

Mobile App Debugging

Charles Proxy excels at mobile app debugging. Both iOS and Android apps route traffic through your computer's proxy.

iOS Setup:

  1. Connect iPhone/iPad to same WiFi as your computer
  2. Go to Settings > Wi-Fi > [Your Network] > Configure Proxy
  3. Select "Manual"
  4. Enter your computer's IP (find it in Help > Local IP Address)
  5. Port: 8888
  6. Install SSL certificate from chls.pro/ssl
  7. Enable certificate trust in Settings

Android Setup:

  1. Connect device to same WiFi
  2. Long-press the network, select "Modify network"
  3. Show advanced options
  4. Set proxy to Manual
  5. Hostname: your computer's IP
  6. Port: 8888
  7. Install certificate (download from chls.pro/ssl)

iOS Simulator:

Charles automatically installs certificates in iOS Simulators:

Help > SSL Proxying > Install Charles Root Certificate in iOS Simulators

Restart the simulator after installation.

Android Emulator:

Launch the emulator with proxy configuration:

emulator @Pixel_4_API_30 -http-proxy http://192.168.1.100:8888

Replace the IP with your actual machine IP.

Dealing with SSL Pinning

Some apps implement SSL pinning, which validates the server's certificate against a hardcoded value. This blocks Charles Proxy's man-in-the-middle approach.

Detecting SSL Pinning:

If Charles shows "SSL Handshake Failed" for an app while Safari works fine, the app likely uses SSL pinning.

Bypassing SSL Pinning (for apps you control or have permission to test):

Option 1: Disable pinning in debug builds

For iOS apps, remove SSL pinning code in debug configurations. For Android, use the network security config shown earlier.

Option 2: Use Frida (requires jailbreak/root)

Install Frida and run a pinning bypass script:

# Install Frida
pip install frida-tools

# Start the app with bypass
frida -U -f com.example.app -l ssl-bypass.js

Universal SSL bypass script for Android:

Java.perform(function() {
    var TrustManagerImpl = Java.use('com.android.org.conscrypt.TrustManagerImpl');
    TrustManagerImpl.checkTrustedRecursive.implementation = function() {
        console.log('[+] Bypassing SSL pinning');
        return Java.use('java.util.ArrayList').$new();
    };
});

Option 3: SSL Kill Switch (iOS jailbreak)

Install SSL Kill Switch 2 from Cydia to disable pinning system-wide.

Note: Only bypass SSL pinning on apps you own or have explicit permission to test.

Automation and Scripting

Charles supports JavaScript-based scripting for automated traffic manipulation.

Basic Script Structure:

function onRequest(event) {
    var request = event.getRequest();
    
    // Log all requests to a specific host
    if (request.getHost() === 'api.example.com') {
        event.console.log('Request: ' + request.getPath());
    }
    
    // Remove tracking headers
    request.removeHeader('X-Tracking-ID');
}

function onResponse(event) {
    var response = event.getResponse();
    
    // Modify response headers
    response.setHeader('X-Debug', 'true');
}

Enable scripting in Tools > Scripting and paste your script.

Practical Script: Remove Cache Headers

function onRequest(event) {
    var request = event.getRequest();
    request.removeHeader('If-Modified-Since');
    request.removeHeader('If-None-Match');
    event.console.log('Removed cache headers from: ' + request.getURL());
}

This forces fresh responses instead of 304 Not Modified.

Headless Mode and CLI Automation

Charles can run without a UI, useful for CI/CD pipelines and automated testing.

Start Charles Headless:

# macOS
/Applications/Charles.app/Contents/MacOS/Charles -headless

# Windows
"C:\Program Files\Charles\Charles.exe" -headless

# Linux
charles -headless

Control via Web Interface:

Enable the web interface in Proxy > Web Interface Settings. Access it at http://control.charles/.

Control Charles programmatically:

# Start recording
curl -x http://localhost:8888 http://control.charles/recording/start

# Stop recording
curl -x http://localhost:8888 http://control.charles/recording/stop

# Enable/disable throttling
curl -x http://localhost:8888 http://control.charles/throttling/enable
curl -x http://localhost:8888 http://control.charles/throttling/disable

# Enable/disable rewriting
curl -x http://localhost:8888 http://control.charles/tools/rewrite/enable

Export Session Data:

# Convert session to JSON
charles convert session.chls session.chlsj

# Convert session to HAR
charles convert session.chls session.har

JSON sessions are easier to parse and analyze programmatically.

Exporting and Sharing Sessions

Charles sessions contain all captured traffic. Export them for collaboration or offline analysis.

Save Session:

File > Save Session As creates a .chls file. Share this with teammates who can open it in their Charles installation.

Export as HAR:

File > Export Session > HAR creates a standard HTTP Archive file. HAR files open in Chrome DevTools or other analysis tools.

Export as Trace:

File > Export Session > Trace includes timing information useful for performance analysis.

Hidden Tricks and Power User Tips

1. Quick Filter by Type

Type json in the filter box to show only JSON requests. Works with any content type: html, css, js, image.

2. Focus Mode

Right-click a host and select "Focus". Charles grays out everything else, reducing visual noise.

3. Repeat Advanced

Right-click a request and select Repeat Advanced. Configure iterations, concurrency, and delays for simple load testing.

4. Compare Requests

Select two requests, right-click, and choose "Compare". Charles shows a diff of headers and body.

5. Find in Session

Edit > Find (Cmd+F) searches across all captured traffic—requests, responses, headers, and bodies.

6. Clear with Shortcut

Cmd+K (Mac) or Ctrl+K (Windows) clears the session. Faster than using menus.

7. Auto-Save Sessions

Tools > Auto Save automatically saves sessions at intervals. Never lose captured traffic to crashes.

8. DNS Spoofing

Tools > DNS Spoofing redirects domains to different IPs without changing your hosts file.

9. Mirror Tool

Tools > Mirror saves all responses to disk automatically. Useful for creating offline copies of websites.

10. External Proxy Chaining

Proxy > External Proxy Settings routes Charles traffic through another proxy. Chain with residential proxies for geo-testing.

Troubleshooting Common Issues

Traffic Not Appearing:

  • Verify proxy settings point to 127.0.0.1:8888
  • Check that macOS/Windows proxy is enabled in Charles
  • Restart the application you're debugging

HTTPS Shows "Unknown" or Encrypted:

  • Install and trust the Charles root certificate
  • Add the domain to SSL Proxying Settings
  • Restart browsers after certificate changes

Mobile Device Not Connecting:

  • Confirm both devices are on same network
  • Check firewall isn't blocking port 8888
  • Verify IP address is correct (not localhost)

App Crashes or Fails:

  • The app might use SSL pinning
  • Try disabling SSL proxying for that domain
  • Check for certificate trust issues

Charles Consumes Too Much Memory:

  • Proxy > Recording Settings limits session size
  • Clear sessions periodically with Cmd+K
  • Disable recording for domains you don't need

Conclusion

Charles Proxy remains one of the most powerful tools for HTTP debugging, API testing, and reverse engineering. Its combination of traffic inspection, modification capabilities, and mobile support makes it invaluable for developers and security researchers.

The techniques covered here—SSL proxying, breakpoints, rewriting, throttling, and automation—handle most debugging scenarios you'll encounter. For web scraping projects, Charles helps discover hidden APIs that are faster and more reliable than HTML parsing.

If you're doing large-scale data collection through proxies, consider pairing Charles with rotating residential proxies from providers like Roundproxies to avoid IP blocks during your research.

Start with basic traffic inspection, then gradually explore advanced features as your debugging needs grow. The investment in learning Charles pays dividends across mobile development, web development, and security testing.