Skip to main content

Using Charles Proxy to examine iOS apps

By Jason Grigsby

Published on August 28th, 2012


I recently did some research into the HTML that Facebook was using in the old version of its iOS app. More on that in a future post. In the meantime, I thought I’d share how to inspect what an iOS app is sending over the network using Charles Proxy.

Before I begin, I must disclose a few things:

  • I am not an expert at using a proxy server nor even at how to use Charles Proxy. I am likely using Charles Proxy in naive ways. I have resisted writing this for some time because I know I am an amateurish hack.
  • Charles Proxy runs on Windows, MacOS and Linux. I have only used the Mac version and will be talking about it.
  • I am a HUGE fan of Charles Proxy. It gives me tremendous joy to be able to see into activity that I otherwise would have no insight into. I feel like the app gives me super powers. I am unabashedly biased about this product.

Ok, let’s start looking at an app shall we?

First things first, you have to buy Charles Proxy. You can get a free trial to begin with. But the full price for the app is $50 with discounts if multiple licenses are purchased.

You will be surprised to learn that I think it is well worth the $50 and one of the best purchases I’ve made. 😉

After you install Charles and have it running, getting your iOS device to recognize Charles is fairly easy. First, make sure your iOS device is on the same network as the machine you’re running Charles on.

Go into your network settings on the iOS device and select the wifi network.

At the bottom of the network settings is the HTTP Proxy settings. They are likely off. Select Manual. Enter the IP address of the machine running Charles for the Server and 8888 for the Port.

If you open Safari (or anything else that makes a network connection), you should receive a prompt in Charles asking if it is ok to let the device connect to your proxy server.

After you approve your device, all future network traffic will be routed through Charles. You can record the traffic by hitting the record button in Charles.

If you see a lot of noise coming from your Mac, turn off the Mac OS X Proxy by unchecking it under the Proxy menu or by pressing Shift-Command-P.

Now you can launch the app you want to inspect and see what it downloads. I’ll use the profile page in the new Facebook app as an example.

When you first load the profile page in Charles proxy, things looked promising. You can see a series of requests, how long they took to download, and their size.

Unfortunately, if you try to see what the server sent in response to the request, or even any details on the request itself, you’ll find that you can’t see much or what you do see will be gibberish.

That’s because Facebook is using SSL to encrypt most of the communication between the app and the server. To see what is going on inside that communication, you need to trick your phone into thinking Charles Proxy’s SSL Certificate is valid for the domains you want to inspect.

Setting this up is a fairly easy two step process.

If you’re using iOS 4 or above, visit on your device and install the certificate for Charles.

If you’re on an older version of iOS, want to use Charles as part of your app development, or want to use it with the simulator, check out Charles Proxy’s iOS SSL documentation.

In the menu under Proxy, select Proxy Settings. Select the SSL tab. Enable SSL Proxying if it isn’t enabled.

You can now add as many domains as you need to complete your task. Wildcards work. For examining the Facebook app, I added the following domains:

  • *
  • *
  • *

Basically, I watched the queries and saw what domains requests came in for that I couldn’t see because they were under SSL, and then I proceeded to add them to the list.

Now that we’ve got SSL proxying in place, let’s take another look at those Facebook requests for the profile page and see if we can see more of what is going on.

Ah… that’s more like it. We can now see the full path requested. If we tap on the response section, we can also see what the content of the response was. In this case, the profile page is still an HTML page even in the new “native” Facebook app.

Now that you have the requests and responses, you can do some really cool stuff. Select all of the relevant requests to look at the total payload delivered.

The overview tab will tell you how many requests were made, how many errors occurred, etc.

The Summary tab will let you know the total size of the assets downloaded and the amount of time it took. You can easily sort the requests to find the largest files or the files that took the most time to download.

Finally, the Chart tab gives several interesting views into the page. The first is a very typical waterfall chart showing you when assets were loaded. I also find the types graph to give a good look at what types of files (e.g., images versus JavaScript) are the biggest assets being downloaded.

Charles allows you to save your session in a Charles Session file or export it as a HAR (HTTP Archive Specification) file or other common formats like CSV which can be shared with others.

After you’re done testing, you’ll need to turn off the HTTP Proxy settings on your phone. I know it seems obvious, but there have been multiple times where I’ve thought a site was down or my network wasn’t working only to realize I forgot to turn HTTP Proxy off.

That’s it. Easy huh?

You can use Charles Proxy to examine mobile web sites or any network requests so long as the device you are testing on supports HTTP Proxies. It’s a great tool to have in your mobile toolbox.


Steve Souders said:

Awesome, Jason. BUT… please keep in mind that configuring your browser to use a proxy will likely change the browser’s behavior, most typically resulting in fewer connections. It’s okay as long you keep this in mind. I’ve helped dozens of developers who were struggling with the fact that they were seeing bad download performance despite all their efforts to do domain sharding and prefetching, only to discover they were behind a proxy. See “Effect of Proxies” here: