Emmanuel Enya I am a computer engineering graduate with five years of professional experience building modern Android applications. I am a huge fan of clean code because clarity is King 😄

Test and debug Android apps like a pro with Charles Web Proxy

6 min read 1887

Test and debug Android apps like a pro with Charles Web Proxy


Testing and debugging are part of any good application development lifecycle. While there are a whole lot of tools and libraries out there for building Android applications, the Charles Web debugging proxy is a very impressive option when you consider the functions it performs.

Using this tool, you can cut down the time spent on debugging and solving issues. After several trials on my own, I was impressed with what I could accomplish and how easily and quickly I could debug and solve issues.

In this article, you will learn about Charles Web Proxy and how to set it up. We’ll cover the following:

What is Charles Web Proxy?

According to the Charles Web Proxy website, Charles is

an HTTP proxy/HTTP monitor/Reverse Proxy that enables a developer to view all of the HTTP and SSL/HTTPS traffic between their machine and the Internet. This includes requests, responses, and the HTTP headers, which contain the cookies and caching information.

In a nutshell, the Charles Web Debugging Proxy is a software application that monitors network activities on personal computers, such as network requests and server responses. It intercepts and changes the data packets in real time.

Charles Web Proxy serves as the middle man

Use cases to consider when using Charles Web Proxy

Testing and debugging can be very frustrating and exhausting. Charles exists to reduce these kinds of work-induced stresses; with Charles in your development arsenal, you can quickly diagnose problems and implement quick fixes. I will outline a few use cases where I find Charles to be handy.

1. Testing feature implementation with states

A typical scenario would be where you depend on a value from the backend to determine certain behaviors on the client-side. Commonly, you may request the backend engineer to effect a change, which works. However, it’s not so fluid a process — often, you end up in a discussion about the changes needed, which reduces productivity.

With Charles, before the response gets delivered to the client-side, you can edit the network response to any data structure of your choice to meet test requirements and more effectively test the app’s response to different states.

2. API endpoints not deployed to staging server

Let’s say you’re working on a feature that requires making a request to the backend server. Chances are that you get blocked because the backend engineer has yet to deploy the API endpoints to the staging environment. In this case, the best you can do would be to make a draft PR while waiting for the backend to meet your needs. This process is not efficient and reduces productivity.

Using Charles, you can mock the network response stated in the business requirements to test the work done. Also, you can safely make a PR ready for review.

3. Debugging and testing errors

Network errors cannot be ignored when building mobile applications. They arise through network requests (i.e., internal server errors). Testing how your client-side logic responds to different network error responses can and rapid development.

You can conveniently mock these responses with Charles Web Proxy.

Summarily, from the above use cases, we can achieve the following with Charles:

  • Intercept and edit network requests and response
  • Mock HTTP failure responses, like Internal Server Error - 500, Bad Request (400)
  • Load HTTP responses from a JSON file

How to set up Charles Web Proxy with Android

I will outline some steps for setting up Charles on your PC and Android device.

Install Charles on your PC

Download the latest version of Charles from the official website. As shown in the screenshot below, you should select the file that matches your PC’s specifications.

Download the latest version of Charles Web Proxy
Download the latest version of Charles Web Proxy

After installation, you will be presented with a window that looks like this:

Post-installation screen

Enable SSL proxy on Charles

SSL proxying intercepts all SSL requests and proxies them in such a way that you can view the contents of the SSL request and response in plain text, rather than just viewing the encrypted text.

Set up proxying for all HTTPS connections like so:

First screen to set up the proxy

Second screen to set up the proxy

Third and final screen to set up the proxy

We defined the host as *, which tells Charles to intercept every network traffic event. The port is set to 443, indicating that the host is secured — HTTPS is the secure and encrypted version of HTTP, and all HTTPS web traffic goes to port 443.

Configuring the Android device to use Charles as its HTTP proxy

Android permits proxy configurations for each wireless network. We will connect the PC and Android device to same network with HTTP proxy settings retrieved from the Charles Help Window.

Retrieve HTTP configurations from the Charles help window, like so:
Retrieve the HTTP configurations from Charles's Help window
Retrieve the HTTP configurations from Charles's Help window

Now, set up the proxy settings on Android.

There are four steps to setting up the proxy for Android
Step 1: Click the edit icon on the top right
Step 2: Under Proxy label, click the dropdown icon to reveal more options
Step 3: Select Manual
Step 4: Enter the HTTP config retrieved from the Charles help window

Charles will prompt you to accept a connection from your mobile device. Click Allow.
Accept the connection from your mobile device

Head on to http://chls.pro/ssl to download your Charles certificate, which will be installed on your Android device.

Navigate to Device Settings and follow the screenshots below for the installation guide.

The first three steps of the installation guide
Step 1: Click Security
Step 2: Click Encryption and Credentials
Step 3: Click Install a certificate
The final three steps of the installation guide
Step 4: Select CA certificate
Step 5: Click Install anyway
Step 6: Select the Charles cert dowloaded in previous steps

Upon completing these steps, Charles should begin intercepting network traffic from your mobile app.

Debugging an Android project with Charles Web Proxy

The proxy we configured above will be used by web browsers, but may not be used by other apps. You need to add configuration to your app in order to have it trust the SSL certificates generated by Charles SSL proxying.

In order to configure your app to trust Charles, you need to add a network security configuration file to your app. This file can override the system default, enabling your app to trust user-installed CA certificates (e.g., the Charles Root Certificate). You can specify that this only applies in debug builds of your application, so that production builds use the default trust profile. You can read more about this on the SSL certificates section of Charles’s website.

Add a network_security_config.xml file to your res/xml/ folder in your app:

      <!-- Trust user added CAs while debuggable only -->
      <certificates src="user" /> 

Specify the network configuration settings in the Manifest.xml file of your application.

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application android:networkSecurityConfig="@xml/network_security_config" ... >

We’re all set to begin using Charles to proxy traffic from our mobile application.

For the purpose of this article, I’ll next demonstrate the use-cases we highlighted earlier, using a movie browser Android project. Clone the project from my GitHub repo.

Testing app behavior when an Internal Server Error is thrown by the server

When writing a piece of software, you want to adopt a defensive programming approach to avoid unexpected outcomes in production, such as ensuring your app can gracefully handle network errors like a 500 internal server error.

Asking your backend engineer to enforce a 500 server error on an endpoint is not a very good approach to run this test for the following reasons:

  1. Other devs using this endpoint might be blocked because the endpoint fails
  2. It might slip the dev’s mind to revert changes, which can cause problems even at the production level
  3. It lowers productivity

Bearing these in mind, we are going to rely on Charles and httpstat to mock a 500 internal server error for our mobile app.

Mocking an error response

Before we proceed to mock an error response, ensure you can intercept and decrypt the response from the TMDB API. If the set up is done correctly, you should have something similar to the screenshot below:

A correctly decrypted TMDB API response

We can then map the API response to Remote, like so:

Map the API response

Edit your map settings and click OK

Save this setting and trigger the API call again from your app. You should see https://httpstat.us/ listed in the view structure like so:

httpstat is listed in the view structure

Basically, we’ve instructed Charles to intercept any request to https://api.themoviedb.org and deliver a response from https://httpstat.us/500 to the mobile device, rather than the original response from https://api.themoviedb.org/3/discover/movierelease_date.gte=2021&api_key=1cbad9b5142e8231f3c5a6d49bb8be0a.

In the screenshot below, I display a toast message to inform the user about the server error.

Displaying the HTTP 500 server error in a toast message
Displaying the HTTP 500 server error in a toast message at the bottom of the screen

Et voilà! We have successfully mocked an internal server error, without needing to shut down the TMDB server. 😀

Testing client-side app logic with mock web responses

Aside from Map Remote, there is a corresponding function, Map Local. They have similar functions, but what differentiates them is the location from which the response is served. The former returns a response from an online server, while the latter serves the response from your local machine via a JSON file.

This function is very handy for testing client app features when endpoints are not ready for use.
The following steps outline when using Map Remote is applicable to using Map Local.

Instead of Map Remote, select Map Local and use a JSON file from your local machine. See the below screenshots for reference:

Under Map Local Settings, click Add
Under Map Local Settings, click Add

Choose the file from your PC

How to use map local instead of map remote
Select Map Local

Using breakpoints

Breakpoints! Yeah, that’s right. You can literally pause the network request and response in real time and edit them. Your client app will then receive the edited response from Charles — the same way as when you put breakpoints in Android Studio, but this is even more sophisticated because you can manipulate the data.

See the screenshot below on how to set breakpoints on a network request:

Click a request and select Breakpoints
Click a request and select Breakpoints
Edit the request and click Execute
Edit the request and click Execute
Edit the response and click Request
Edit the response and click Request

Using breakpoints on Charles will happen in the order in which the images appear.


Charles Web Proxy is a very handy tool for software development. Especially on Android, we can manipulate response data to represent different ViewStates, thus speeding up development and testing.

If you followed through to the end, well done! Let me hear you thoughts about this tool in the comments sections. Thank you!

LogRocket: Instantly recreate issues in your Android apps.

LogRocket is an Android monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your Android apps.

LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.

Start proactively monitoring your Android apps — .

Get set up with LogRocket's modern error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID
  2. Install LogRocket via npm or script tag. LogRocket.init() must be called client-side, not server-side
  3. $ npm i --save logrocket 

    // Code:

    import LogRocket from 'logrocket';
    Add to your HTML:

    <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
    <script>window.LogRocket && window.LogRocket.init('app/id');</script>
  4. (Optional) Install plugins for deeper integrations with your stack:
    • Redux middleware
    • NgRx middleware
    • Vuex plugin
Get started now
Emmanuel Enya I am a computer engineering graduate with five years of professional experience building modern Android applications. I am a huge fan of clean code because clarity is King 😄

Leave a Reply