Charles Proxy Tutorial for iOS

Learn how to use Charles for iOS and macOS to inspect encrypted and unencrypted network traffic for both your own apps and third-party apps. By Irina Galata.

5 (9) ·

Download materials
Save for later
Update note: Irina Galata updated this tutorial for Xcode 12, Swift 5 and iOS 14. Aaron Douglas wrote the original.

Let’s face it — we’ve all written code that doesn’t work correctly, and debugging can be hard. It’s even more difficult when you’re talking to other systems over a network.

Fortunately, Charles Proxy can make network debugging much easier.

Charles Proxy sits between your app and the internet. You configure your simulator or iOS device to pass all networking requests and responses through Charles Proxy, so you’ll be able to inspect and even change data midstream to test how your app responds.

In this tutorial, you’ll get hands-on experience with this. In the process, you’ll learn all about:

  • Proxies and how they work on macOS and iOS.
  • Preparing your system to use Charles.
  • Snooping on apps.
  • Simulating and troubleshooting slow networks.
  • Troubleshooting your own apps.

Ready to dive in?

Getting Started

Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial.
Then, download the latest version of Charles Proxy for Mac (v4.6.1 at the time of writing). Double-click the DMG file and drag the Charles icon to your Applications folder to install it.

Charles Proxy isn’t free, but there’s a free 30-day trial. Charles will only run for 30 minutes in trial mode, so you may need to restart it throughout this tutorial.

Note: Charles is a Java-based app and supports macOS, Windows and Linux. This Charles Proxy tutorial is for macOS, and some things may be different on other platforms.

Launch Charles. It should ask for permission to automatically configure your network settings. If it doesn’t, press Command-Shift-P to manually have Charles ask for this permission.

Charles Proxy Network Settings

Click Grant Privileges and enter your password if prompted. Charles starts recording network events as soon as it launches, so you should already see events popping into the left pane.

Charles Proxy Network Recording

Note: If you don’t see any events, you may have not granted permissions or may have another proxy already set up. A VPN can also make problems. See Charles’ FAQ page for troubleshooting help.

Exploring the App

The user interface is easy to understand without much experience.

Charles Proxy Toolbar

Many goodies are hidden behind buttons and menus, and the toolbar has a few items you should know about:

  • “Broom” clears the current session and all recorded activity.
  • “Record/Pause” is red when Charles is recording events and gray when stopped.
  • “Lock” starts/stops SSL proxying.
  • The middle buttons from the “Tortoise” to the “Checkmark” provide access to common actions, including throttling, breakpoints and request creation.
  • The last two buttons provide access to commonly used tools and settings.

For now, stop recording by clicking the red Record/Pause button.

Under the toolbar is a toggle between Structure and Sequence. With Sequence selected, the top pane contains a summary of all the recorded network requests, while the main pane contains detailed information about the selected request.

With Structure selected, the top pane is replaced by a left-hand pane of the same data, grouped by site address. You can still see individual requests by expanding each individual site.

Charles Proxy Sequence List

Select Sequence to see all events in a continuous list sorted by time. You’ll likely spend most of your time on this screen when debugging your own apps.

Charles merges the request and response into a single screen by default. However, you can split them into separate events.

Choose Charles ▸ Preferences and select Viewers. Uncheck Combine request and response and press OK. You’ll need to restart Charles for the change to take effect.

Try poking around the user interface and looking at events. You’ll notice one peculiar thing: You can’t see most details for HTTPS events!

SSL/TLS encrypts sensitive request and response information. You might think this makes Charles pointless for all HTTPS events, but Charles has a sneaky way of getting around encryption.

More About Proxies

You may be wondering: “How does Charles do its magic?”

Charles is a proxy server, which means it sits between your app and computer’s network connections. When Charles configured your network settings, it changed your network configuration to route all traffic through it. This allows Charles to inspect all network events to and from your computer.

Proxy servers are in a position of great power, but this also implies the potential for abuse. This is why SSL is so important: Data encryption prevents proxy servers and other middleware from eavesdropping on sensitive information.

Network Diagram

However, in this case, you want Charles to snoop on your SSL messages to let you debug them.

SSL/TLS encrypts messages using certificates generated by trusted third parties called certificate issuers.

Charles can also generate its own self-signed certificate, which you can install on your Mac and iOS devices for SSL/TLS encryption. Since this certificate isn’t issued by a trusted certificate issuer, you’ll need to tell your devices to explicitly trust it. Once installed and trusted, Charles will be able to decrypt SSL events!

When hackers use middleware to snoop on network communications, it’s called a “man-in-the-middle” attack. In general, you DON’T want to trust any random certificate, or you could compromise your network security!

There are some cases where Charles’ sneaky man-in-the-middle strategy won’t work. For example, some apps use SSL pinning for extra security. SSL pinning means the app has a copy of the web server’s public key, and it uses this to verify network connections before communicating. Since Charles’ key wouldn’t match, the app would reject the communication.

Besides logging events, you can also use Charles to modify data on the fly, record it for later review and even simulate bad network connections.

Charles Proxy powerful image

Charles is powerful!

Charles Proxy and Your iOS Device

For years, the only way to proxy traffic from a physical iOS device through Charles Proxy was to tell your iOS device to send all network traffic to your computer. This is still a common practice you’ll cover, but first, you’ll check out the Charles Proxy for iOS app!

Open the App Store on your iOS device and search for Charles Proxy. Unfortunately, there isn’t a free version of the iOS app, so you’ll have to buy it if you want to follow along with this section.

Note: Don’t want to purchase the iOS app? Worry not! You can skip this section and continue below, where you’ll learn how to route your app’s network traffic to your Mac.

Charles Proxy on the App Store

Install the app on your device and open it. The initial screen shows the proxy is inactive. There’s a switch and an overview of some key stats for any running session. Toggle the Status Switch on.

Once asked for permission to install VPN Configurations, tap Allow.

Charles asking for VPN Configurations permission

The status will change to Active.

Charles Proxy initial screen

Tap the Current Session disclosure indicator arrow, and the app will navigate to a view comparable to the top pane on the desktop app. If you don’t see any requests, switch to Safari and load a webpage.

Requests in the current session

Tap any of the individual requests and you’ll drill down to a detailed view for that request. As with the desktop app, any SLS/TLS encrypted traffic is still obfuscated.

Unknown SSL traffic

It’s time to fix that. :]

Installing Charles’ Certificate

Still within the Charles Proxy app, navigate back to the initial screen by tapping the back arrow at the top left of your screen twice. With the proxy still active, tap the Settings gear at the top left of the screen. Select SSL Proxying.

SSL Proxy settings

Now, at the bottom of this screen, you’ll find detailed instructions for installing and trusting the Charles Proxy CA Certificate. First, install the certificate using the button in the app. Your device will app switch to Safari and ask for permission to install the profile.

Note: If you have an Apple Watch paired with your device, it’ll ask whether to install the profile on the device or the watch. Choose iPhone.

Once the profile is installed, open the Settings app. You’ll see a new Profile Downloaded option. Tap it and choose the Install option in the top-right corner.

Installing the certificate

You’ll be prompted for your device passcode, if you have one, followed by a confirmation screen warning you that this certificate is unverified. Tap Install again. Finally, an action screen will appear from the bottom of the screen with a final confirmation. Apple really wants to make sure you want to install this. :]

Again, don’t install just any random certificate, or else you may comprise your network security!

Verifying the certificate

At the end of this Charles Proxy tutorial, you’ll also remove this certificate.

Trusting Charles’ Certificate

You’ll get a confirmation screen that the profile is installed. Next, you need to trust that certificate. Still in the Settings app, navigate to General ▸ About ▸ Certificate Trust Settings. Find the Charles Proxy certificate and toggle the switch to on. A warning dialog will appear. Select Continue.

Switch back to the Charles Proxy app and the certificate status will now say Trusted. Toggle the Enabled switch at the top of the screen to on.

Charles Proxy with a trusted certificate

In Charles, navigate back to the main Settings page and save your changes. Open the current session and clear all the traffic using the broom icon in the bottom-left corner of the screen. Navigate to Safari and reload a webpage. Then, navigate back to Charles Proxy. Tap one of the requests and tap Enable SSL Proxying.

Enabled SSL proxying for a particular domain

Go back to the current session and clear the session once again. Re-open Safari and reload the page a final time. Now, if you navigate back to Charles Proxy, the URL for which you enabled SSL proxying will have a blue network icon rather than a lock icon.

Request with SSL proxying enabled

First, tap the URL to see the full detail of each request.

Requests to a URL with SSL proxying enabled

Next, tap into a request for more detail.

Request body

Then, tap View body to view the full response body. Hurrah! :]

Response body

This example used Safari, but the following process will work when opening any app on your device, including your own, when wanting to debug your app’s networking.

Next, tap back to the request page and disable SSL proxying. Tap back to the initial view and set the Charles Proxy status to Inactive to stop proxying traffic.

Proxying iOS Traffic Using Charles Proxy for macOS

What happens if you want to inspect traffic on a simulator, or you don’t have the Charles Proxy iOS app? No problem! It’s simple to set up Charles to proxy traffic from any computer or device on your network, including your iOS devices.

Setting Up Your Device

Open Charles Proxy on your Mac and turn off macOS proxying by clicking Proxy (drop-down menu) ▸ macOS Proxy to uncheck it. This way, you’ll only see traffic from your iOS device.

Next, click Proxy ▸ Proxy Settings, click the Proxies tab and make note of the port number, which by default should be 8888.

Proxy Settings

Then, click Help ▸ Local IP Address and make note of your computer’s IP address. If there’s more than one IP address, pick en0.

Now, grab your iOS device. Open Settings, tap Wi-Fi and verify you’re connected to the same network as your computer. Then, tap the button next to your Wi-Fi network. Scroll down to the HTTP Proxy section, select Configure Proxy and then tap Manual.

Enter your Mac’s IP address for Server and the Charles HTTP Proxy port number for Port. Tap Save.

Head back to the Charles macOS app. Tap the Record/Pause button if you’re not already recording traffic.

You should get a pop-up warning from Charles on your Mac asking to allow your iOS device to connect. Click Allow. If you don’t see this immediately, that’s OK. It may take a minute or two for it to show up.

iOS Device Connection Permission

Now you should start to see activity from your device in Charles! But note that you can’t view SSL traffic just yet. As with the iOS app, you’ll need to install a certificate from Charles.

Installing a Certificate on Your Device

Note: These instructions also work for installing a certificate on a simulator, with two differences. First, you must re-enable macOS Proxy in Charles’ Proxy menu. Second, you’ll find the downloaded profile on the Settings ▸ General page instead of the main Settings page.

Still on your iOS device, open Safari and navigate to On the pop-up, tap Allow.

Install certificate from the Charles website

Note: Again, if you have an Apple Watch paired with the device, iOS will prompt you to choose between your device and watch for installing the profile. Select iPhone.

In what should now be a familiar journey for you, switch to Settings and install the profile. Tap Install, enter your passcode (if set up) and tap Install again after the warning appears. Then, tap Install one more time. Finally, tap Done.

As before, open the Settings app and navigate to General ▸ About ▸ Certificate Trust Settings. Trust the certificate you just installed.

Next, in the macOS Charles app, select Proxy ▸ SSL Proxying Settings. Ensure Enable SSL Proxying is checked, and add a value for the traffic you want to inspect.

Enable SSL Proxying

Note: If you don’t know what values to put here, you can select a request in the app with the secondary (right) click and select Enable SSL Proxying from there.

Enable SSL Proxying

You’ll now see the full request and response bodies for that connection.

Snooping on Someone Else’s App

If you’re like most developers, you’re curious how things work. Charles enables this curiosity by giving you tools to inspect any app’s communication.

Go to the App Store on your device and find and download Weather Underground. This free app is available in most countries. If it’s not available, or you want to try something else, feel free to use a different app.

You’ll notice a flurry of activity in Charles while you’re downloading Weather Underground. The App Store is pretty chatty!

Once the app is installed, launch the app and click the broom icon in Charles to clear recent activity.

Tap Search, enter the zip code 90210 and select Beverly Hills as your location. Then, tap View. If you were to use your current location, the URL that the app fetches could change if your location changes, which might make some later steps in this Charles Proxy tutorial harder to follow.

There are tons of sites listed in the Structure tab! This is a list of all activities from your iOS device.

Activities structured in Charles Proxy

Switch to the Sequence tab and enter weather in the filter box to show only weather traffic.

You’ll now see a few requests to Click one.

The Overview section shows some request details, but not much, as you haven’t enabled SSL proxying for

Click Proxy ▸ SSL Proxying Settings and Add. Enter for the Host, leave Port empty and click OK to dismiss the window.

SSL Proxying Settings

Back in the Weather Underground app, pull down to refresh and re-fetch data. If the app doesn’t refresh, you might need to kill it from the multitasking view and try again.

Huzzah! Charles shows unencrypted requests!

Charles unencrypted requests

Look for a request with a URL containing /v3/wx/observations/current. This contains the payload used to populate the weather screen.

Modifying the Response

Time to have some fun and change the data before the app gets it. Can you get the app to break or act funny?

In Charles, right-click the request within the Sequence list, and click Breakpoints in the pop-up list. Then, click Proxy ▸ Breakpoint Settings, double-click the breakpoint you added and make sure to empty Query:

Charles breakpoints

This ensures you intercept any request containing this path, regardless of the query parameters, and Charles will pause and let you edit both the request and response.

Again on your device, pull down to refresh the app.

A new tab titled Breakpoints should pop up with the outgoing request. Click Execute without modifying anything. A moment later, the Breakpoints tab should again reappear with the response.

Click the Edit Response tab near the top. At the bottom, select JSON text. Scroll down and find temperature and change its value to something unrealistic like 98000. Click Execute.

Note: If you take too long editing the request or response, the app may silently time out and never display anything. If the edited temperature doesn’t appear, try again a little more quickly.

Modified Temperature

98000°F is incredibly hot! It seems like the app doesn’t adjust the font size for temperatures with more than five digits. That’s a definite one-star rating. ;]

Back in Charles, delete the breakpoint you set by going to Proxy ▸ Breakpoint Settings.

Uncheck the entry for to temporarily disable it, or highlight the row and click Remove to delete it. Pull down to refresh, and the temperature should return to normal.

Simulating Slow Networking

Now, you’ll simulate slow networking. Click the Tortoise icon to start throttling. Next, click Proxy ▸ Throttle Settings to see available options. The default is 56 kbps, which is pretty darn slow. You can also tweak settings here to simulate data loss, reliability issues and high latency.

Try refreshing the app, zooming the map and/or searching for another location. Painfully slow, right?

It’s a good idea to test your own app under poor network conditions. Imagine your users on a subway or entering an elevator. You don’t want your app to lose data, or worse, crash in these circumstances.

Apple’s Network Link Conditioner provides similar throttling capabilities, yet Charles allows for much finer control over network settings. For example, you can apply throttling to only specific URLs to simulate just your servers responding slowly instead of the entire connection.

Remember to turn off throttling when you’re done with it. There’s nothing worse than spending an hour debugging only to discover you never turned off throttling!

Troubleshooting Your Own Apps

Charles Proxy is especially great for debugging and testing your own apps. For example, you can check server responses to ensure you have JSON keys defined correctly and expected data types are returned for all fields. You can even use throttling to simulate poor networks and verify your app’s timeout and error-handling logic.

Before you build and run, add the following two hosts to Charles’ SSL Proxying Settings as you learned to do above:


Then, build and run the sample app on your device or simulator.

Starter project app

This app shows a list of all the countries with some short info on each of them. But what happened to the icons? It looks like there was an error decoding the data from the service. You’ll see if Charles can help you get to the bottom of the problem.

Switch to Charles Proxy (on your Mac) and in the Sequence tab, change the filter to You’ll see that all the requests failed with a 404 error, as no image was found for any country:

Charles Proxy 404 Response

As you can see in Charles, you use a three-letter code to fetch an image of a country flag. But according to, you need to use a two-letter country code to get it working!

Now, change the filter in the Sequence tab to to monitor what data you receive from this service to see whether you can get the code:

    "name": "Afghanistan",
    "topLevelDomain": [".af"],
    "alpha2Code": "AF",
    "alpha3Code": "AFG",
    "callingCodes": ["93"],
    "capital": "Kabul",
    "altSpellings": ["AF", "Afġānistān"],
    "region": "Asia",
    "subregion": "Southern Asia",
    "population": 27657145,
    "latlng": [33.0, 65.0],
    "demonym": "Afghan",
    "area": 652230.0,
    "gini": 27.8,
    "timezones": ["UTC+04:30"],
    "borders": ["IRN", "PAK", "TKM", "UZB", "TJK", "CHN"],
    "nativeName": "افغانستان",
    "numericCode": "004",
    "currencies": [{
        "code": "AFN",
        "name": "Afghan afghani",
        "symbol": "؋"

The response contains two country codes called alpha2Code and alpha3Code. In Xcode, open Country.swift and take a closer look at CodingKeys. Indeed, the code was wrong!

Replace the following:

case code = "alpha3Code"


case code = "alpha2Code"

Build and run the app again.

Fixed CountryFlags App

Success! This is a trivial but good demonstration of how viewing networking traffic in Charles Proxy can help you uncover bugs in your networking code.

Removing Charles’ Certificate

In the past, Charles created a shared certificate across everyone’s devices that used it. Fortunately, Charles now creates unique certificates. This significantly reduces the chance of a man-in-the-middle attack based on this certificate, but it’s still technically possible. Therefore, you should always remember to remove Charles’ certificates when you’re done with it.

First, remove the certificate(s) from macOS. Open Keychain Access, which is located in Applications ▸ Utilities. In the search box, type Charles Proxy and delete all the certificates the search finds. There’s most likely only one to delete. Close the application when you’re done.

Next, remove the certificates from your iOS device. Open the Settings app and navigate to General ▸ Profiles. Under Configuration Profiles, you’ll see one or more entries for Charles Proxy. Tap one and then tap Remove Profile. Enter your passcode (if required) and confirm the removal. Repeat this for each Charles Proxy certificate.

Profiles & Device Management isn’t available in iOS Simulator. To remove the Charles Proxy certificates, reset the simulator by clicking the Hardware menu and then Erase All Content and Settings….

You should also turn off the Proxy for your Wi-Fi connection on your iPhone by opening Settings and visiting Wi-Fi, tapping the button, scrolling down to the HTTP Proxy section, selecting Configure Proxy and then tapping Off.

Where to Go From Here?

Download the fixed version of the project using the Download Materials button at the top or bottom of this tutorial.

And now you should know how to use Charles Proxy. It has a ton more features that aren’t covered in this tutorial, and there’s a lot more you can do with what you learned today. Check out Charles’ website for more documentation. The more you use Charles, the more features you’ll discover.

You can also read more about SSL/TLS on Wikipedia.

We hope you enjoyed this tutorial. Do you know of any other useful apps for debugging networking? Or do you have any debugging battle stories? If you have any questions or comments, please join the forum discussion below!