Proxy Tools: Charles and Proxyman
See every request your app sends, change server responses on the fly, and simulate errors and slow networks. A practical introduction to Charles and Proxyman for mobile testers.
A banking app shows the wrong balance for some users. The developers say “the app just displays what the server sends”. The backend team says “the server sends the right number”. Who’s right?
A tester with a proxy tool settles it in two minutes: she opens the request, looks at the response, and sees the server sends "balance": 1250.5 while the app shows $125.05. It’s an app bug, and she has the evidence. No guessing, no meetings.
That’s the superpower of a proxy toolProxy toolA program that sits between the app and the server so you can watch and change network traffic.Open in glossary →: it lets you see and change the conversation between the app and its server.
What a proxy does
Normally the app on your phone talks straight to the server. With a proxy, you tell the phone to send its traffic through a program on your computer first. The proxy sits in the middle: it records every request and response, and can pause, edit, slow down or replace them.
Phone
Wi-Fi proxy points to your computer
Proxy on your computer
Charles, Proxyman, Fiddler, mitmproxy
Server
api.shop.example
For HTTPS traffic, the phone must trust the proxy’s root certificate. The proxy decrypts the traffic, shows it to you, and encrypts it again before passing it on.
This is a man-in-the-middle setup, the same thing an attacker would try to do, except you do it on purpose, on your own test device, with your team’s permission. For HTTPSHTTPSThe secure version of HTTP; traffic between the browser or app and the server is encrypted.Open in glossary → traffic, the phone must trust the proxy’s own certificateSSL certificateThe certificate that lets a browser or app verify a server's identity and encrypt traffic (HTTPS).Open in glossary →, otherwise the encryption prevents the proxy from reading anything.
Why testers use proxies
| What you can do | Why it’s useful | Example |
|---|---|---|
| See requests and responses | Find out whether a bug is in the app or the server | The server sends the right price, the app shows the wrong one |
| Verify analytics events | Check events fire once, at the right moment, with the right data | purchase event sent twice, or with the wrong currency |
| Check what data is sent | Spot privacy and security problems | Password in the URL, full card number in a response, tokens over plain HTTP |
| Simulate errors | Test how the app handles a 500, 401 or 404 you can’t trigger otherwise | The app shows a blank screen on a server error |
| Breakpoints | Pause a request or response and edit it before it continues | Change a price to 0.01, a name to 300 characters, or a status to 500 |
| Map Local / Map Remote | Answer with a local file, or send the request to another server | Return an empty list; point the app at the staging server |
| Throttle | Slow down all traffic from the phone | Check loading states on 3G (see Network Conditions) |
| Repeat requests | Send the same request again, many times | Does sending “place order” twice create two orders? |
Try it: the proxy playground
Play with a proxy before setting up a real one. This grocery app is well built: it handles errors, empty lists and slow responses correctly. Use the tools and watch how it reacts.
🧪 Proxy playground
The grocery app on the phone talks to its server through the proxy. Try this: turn on Breakpoint, tap refresh in the app, change a price or the status code, then press Execute. Then try Map Local and Throttle.
- Use the app on the phone to see its traffic here.
Select a request to see its details.
FreshCart
Setting up a real proxy
The steps are similar for every tool. Here’s the big picture, then the details for Charles and Proxyman.
- Install the proxy on your computer and start it. Note its IP address and port (Charles uses 8888 by default, Proxyman 9090).
- Put the phone and computer on the same Wi-Fi network. Office “guest” networks often block devices from seeing each other; use a network that allows it.
- Set the phone’s Wi-Fi proxy to Manual, with the computer’s IP and the proxy port. Open any page and accept the “allow this device?” prompt on the computer.
- Install and trust the proxy’s root certificate on the phone, so HTTPS traffic can be decrypted.
- Enable SSL proxying for the hosts you want to inspect (for example
api.shop.example). - Use the app and watch the traffic. When you’re done, remove the proxy setting from the phone.
Charles and Proxyman specifics
Charles Proxy runs on macOS, Windows and Linux (paid, with a free trial).
- See your IP and port: Help → Local IP Address and Proxy → Proxy Settings (default port 8888).
- Certificate instructions for phones: Help → SSL Proxying → Install Charles Root Certificate on a Mobile Device or Remote Browser. With the phone’s proxy set, open chls.pro/ssl in the phone’s browser to download it.
- Decrypt HTTPS: Proxy → SSL Proxying Settings… → add the host (and port 443), or right-click a host → Enable SSL Proxying.
- Tools: Breakpoints (right-click a request), Tools → Map Local / Map Remote / Rewrite, Proxy → Throttle Settings, and Repeat / Repeat Advanced on any request.
Proxyman is a native macOS app (with Windows and Linux versions, and a free tier).
- See your IP and port in the app’s status bar or Certificate → Install Certificate on iOS → Physical Devices…, which shows step-by-step instructions (default port 9090).
- With the phone’s proxy set, open proxy.man/ssl in the phone’s browser to download the certificate. There are similar guides under Certificate for Android devices, the iOS Simulator and the Android emulator.
- Decrypt HTTPS: right-click a domain → Enable SSL Proxying (Proxyman shows
<encrypted>until you do). - Tools: Tools → Breakpoint, Map Local, Map Remote, Scripting, Network Conditions (throttling), and Repeat on any request.
Trusting the certificate on the phone
- Settings → Wi-Fi → tap the ⓘ next to your network → Configure Proxy → Manual. Enter the computer’s IP and port, and save.
- In Safari, open the certificate URL (e.g.
chls.pro/sslorproxy.man/ssl) and allow the profile download. - Settings → General → VPN & Device Management → tap the downloaded profile → Install.
- Settings → General → About → Certificate Trust Settings → turn on full trust for the proxy’s root certificate. Skipping this step is the most common reason HTTPS traffic still fails.
The iOS Simulator is easier: Proxyman and Charles can install the certificate into the simulator for you, and the simulator uses the Mac’s proxy settings.
- Settings → Network & internet → Internet / Wi-Fi → your network → edit (pencil or gear) → Advanced options → Proxy → Manual. Enter the computer’s IP and port.
- Download the certificate from the proxy’s URL in the phone’s browser.
- Install it as a CA certificate: usually Settings → Security & privacy → More security settings → Encryption & credentials → Install a certificate → CA certificate (the exact path differs between manufacturers and Android versions).
- Important: since Android 7, apps ignore user-installed certificates by default. Ask developers for a debug build whose network security config trusts user certificates, for example:
<!-- res/xml/network_security_config.xml (debug builds only) -->
<network-security-config>
<debug-overrides>
<trust-anchors>
<certificates src="user" />
</trust-anchors>
</debug-overrides>
</network-security-config>In the Android Emulator you can set the proxy in Extended controls → Settings → Proxy.
Other tools
- Fiddler (Fiddler Everywhere for macOS, Windows and Linux; Fiddler Classic for Windows) does the same job and is popular in Windows teams.
- mitmproxy is free and open source: a command-line tool with a web interface (
mitmweb) and Python scripting, great for automation. - Browser DevTools show web traffic without any proxy setup, and a HAR fileHAR fileA file that records every network request and response a web page made.Open in glossary → lets you share a recording with developers.
Safety and ethics
What to look for
Data and privacy
- Passwords, tokens or personal data in URLs (query parametersQuery parameterData in a URL after the ?, like ?q=mug&sort=price, often used to keep search and filter state.Open in glossary → end up in server logs and analytics).
- Responses that contain more data than the screen shows (full card numbers, other users’ data, internal IDs, password hashes).
- Any traffic over plain
http://instead ofhttps://. - Tokens that don’t change after logout, or that keep working after logout.
Analytics
- Each event fires exactly once, at the right moment, with the right properties (product ID, price, currency).
- No events fire before the user gives consent, if the app asks for it.
Error handling
- Use breakpoints or rules to return
500,503,401,404, an empty list,nullvalues, huge values and broken JSON. The app should show a helpful message, an empty stateEmpty stateThe screen a user sees when there is no content yet, like an empty cart or no search results.Open in glossary → or a login prompt, never a crash or blank screen. - Slow responses (throttling or a paused breakpoint) show a loading state.
Server-side checks
- Edit a request before it reaches the server: change the price, quantity, coupon, user ID or role. The server must validate everything and never trust values that only the app controls. This is classic security testingSecurity testingChecking that data and features are protected from unauthorized access and attacks.Open in glossary →.
- Repeat a request (place order, apply coupon, transfer money). It shouldn’t apply twice. See idempotencyIdempotencyAn action that gives the same result no matter how many times it is repeated.Open in glossary →.
Common bugs found with a proxy
| # | Bug | What you see | Typical severity |
|---|---|---|---|
| 1 | Sensitive data in the URL | ?password=… or ?token=… in the request list | High |
| 2 | Over-sharing API | Response includes full card number, other users’ emails, internal flags | High–Critical |
| 3 | Duplicate analytics events | Same event appears twice per action | Medium |
| 4 | Crash on server error | Blank screen or crash after a 500 | High |
| 5 | Crash on empty or missing data | App crashes when a list is empty or a field is null | High |
| 6 | Server trusts the client | Editing price/total in the request changes what is charged | Critical |
| 7 | Duplicate actions on repeat | Repeating “place order” creates a second order | High |
| 8 | Too many requests | The same data is downloaded 5 times per screen | Low–Medium |
Find the bug
Time for a real investigation. This grocery app has six bugs that you can only find by looking at (or changing) its traffic. Log in, add items, pay, and use Breakpoint (with Requests and/or Responses), Map Local and the request details. Don’t forget to read the response bodies.
🐞 Bug hunt: Grocery app traffic
This demo has 6 hidden bugs. Explore it like a tester, then check your findings.
Welcome back
Log in to FreshCart
anna@example.com
Password
••••••••••••
Stuck on a blank screen? Restart the app like a real user would.
- Log in on the phone to start capturing traffic.
Select a request to see its details.
- 1
Hint: Log in and read the path of the first request.
- 2
Hint: Tap + once on one product and count the requests to collect.metrics.example.
- 3
Hint: Turn on Breakpoint (Responses), refresh the shop and change the products response to status 500.
- 4
Hint: Turn on Map Local and refresh the shop.
- 5
Hint: Add items, turn on Breakpoint for Requests, tap Pay and edit the total in the order request.
- 6
Hint: Open the GET /v1/me response body.
Example test cases
TC-PRX-001Login does not expose credentials in the URLnegativehigh
Preconditions
- Proxy recording with SSL proxying enabled for the API host
Steps
- Log out
- Log in with a test account
- Inspect the login request in the proxy
Expected result
Credentials are sent in the body of a POST request over HTTPS. The URL contains no password, email or token.
TC-PRX-002Purchase analytics event fires once with correct datapositivemedium
Preconditions
- Proxy recording
- Basket contains 1 item for $12.50
Steps
- Complete checkout
- Filter the proxy by the analytics host
Expected result
Exactly one "purchase" event is sent after the order succeeds, with value 12.50 and currency USD.
TC-PRX-003Product list handles a 500 errornegativehigh
Preconditions
- Response breakpoint (or rewrite rule) on GET /v1/products
Steps
- Pull to refresh the product list
- Change the response status to 500 and execute
Expected result
A friendly error with a "Try again" button is shown. No crash, no blank screen. Try again loads the list once the breakpoint is removed.
TC-PRX-004Product list handles an empty responseedgehigh
Preconditions
- Map Local rule returns {"products": []} for GET /v1/products
Steps
- Open the shop
Expected result
An empty state is shown ("Nothing on the shelves right now"). The app does not crash.
TC-PRX-005Server ignores a manipulated order totalnegativehigh
Preconditions
- Request breakpoint on POST /v1/orders
- Basket total is $7.99
Steps
- Tap Pay
- Change "total" to 0.01 in the request body and execute
Expected result
The server rejects the order or charges the correct $7.99 calculated from its own prices.
TC-PRX-006Repeating the place-order request does not create a second orderedgehigh
Preconditions
- One order just placed while recording
Steps
- Select the POST /v1/orders request in the proxy
- Use Repeat
- Open order history in the app
Expected result
Only one order exists. The repeated request is rejected or returns the original order (idempotency key).
Tip: click a test case to expand it.
Checklist
Proxy testing checklist
0 of 12 checked
Check your understanding
Quick quiz
0/5 answered · 0 correct
1.You installed the proxy certificate on an iPhone, but HTTPS requests still fail. What did you most likely forget?
2.An Android app shows no decrypted traffic, although the certificate is installed on the phone. What is a likely reason?
3.Which proxy feature lets you change a server response before the app receives it?
4.You change the price in the order request to 0.01 and the server charges 0.01. Whose bug is it, and how severe?
5.Requests from one app always fail with SSL errors in the proxy, while other apps work. What should you do?
Key takeaways
- A proxy sits between the app and the server, so you can see and change every request and response.
- Use it to tell app bugs from server bugs, verify analytics, check what data is sent, simulate errors, throttle and repeat requests.
- Setup: same network, Wi-Fi proxy on the phone, install and trust the root certificate, enable SSL proxying. Android debug builds must trust user certificates, and pinning needs a QA build.
- The most valuable proxy findings are security bugs: secrets in URLs, over-sharing APIs and servers that trust client values.
- Stay safe: test accounts only, don’t share captures with secrets, and remove the proxy and certificate when you’re done.
Finished this page?Nice work, this page is complete!
Mark it as done to track your progress. It's saved in this browser, no account needed.
Its review cards are now in Bites ⚡