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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Charles Proxy Tutorial for iOS
25 mins
- Getting Started
- Exploring the App
- More About Proxies
- Charles Proxy and Your iOS Device
- Installing Charles’ Certificate
- Trusting Charles’ Certificate
- Proxying iOS Traffic Using Charles Proxy for macOS
- Setting Up Your Device
- Installing a Certificate on Your Device
- Snooping on Someone Else’s App
- Modifying the Response
- Simulating Slow Networking
- Troubleshooting Your Own Apps
- Removing Charles’ Certificate
- Where to Go From Here?
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.
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 api.weather.com. Click one.
The Overview section shows some request details, but not much, as you haven’t enabled SSL proxying for api.weather.com.
Click Proxy ▸ SSL Proxying Settings and Add. Enter api.weather.com for the Host, leave Port empty and click OK to dismiss the window.
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!
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:
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.
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 api.weather.com 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:
- www.countryflags.io
- restcountries.eu
Then, build and run the sample app on your device or simulator.
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 countryflags.io. You’ll see that all the requests failed with a 404 error, as no image was found for any country:
As you can see in Charles, you use a three-letter code to fetch an image of a country flag. But according to countryflags.io, you need to use a two-letter country code to get it working!
Now, change the filter in the Sequence tab to restcountries.eu 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"
With:
case code = "alpha2Code"
Build and run the app again.
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.