MediumIntroduction to Charles Proxy. Using Charles Proxy For Testing Tutorial | by J3 | Jungletronics | Medium
Sitemap
Jungletronics

Education & STEAM Learning by building. Practical explorations in AI, programming, electronics, robotics, IoT, and other STEAM topics — from ideas and experiments to working products. Follow and build with us.

Introduction to Charles Proxy

Using Charles Proxy For Testing Tutorial

15 min readDec 13, 2024

--

Introduction

In this post, we’ll take a closer look at Charles Proxy, a powerful tool for developers and testers who need to understand what’s happening beneath the surface of their applications.

Whether you’re debugging an application, troubleshooting HTTP/HTTPS traffic, or testing a web feature, Charles Proxy gives you a clear view of the communication between your browser, application, and server — making it a valuable companion for network analysis and testing.

Welcome!

Press enter or click to view image in full size
Charles is a web proxy (HTTP Proxy/HTTP Monitor) that runs on your computer. Your web browser (or any other internet application) is configured to access the internet through Charles, enabling it to record and display all the data sent and received.

What Is Charles Proxy?

Charles Proxy is a web debugging proxy that runs locally on your computer. When you configure your browser or another internet-enabled application to route its traffic through Charles, it captures, displays, and records the HTTP and HTTPS communication flowing between the client and the server.

In simple terms, Charles sits between your application and the internet, giving you a detailed view of what is happening behind the scenes. You can inspect requests and responses, analyze headers and payloads, troubleshoot connectivity issues, and understand how an application communicates with its backend services.

For HTTPS traffic, Charles can also perform SSL Proxying, allowing authorized traffic to be decrypted and inspected during testing.

Motivation

When developing mobile apps, it’s essential to understand the risks of exposing API keys, client secrets, and other sensitive credentials — even when HTTPS is used.

Tools like Charles Proxy are invaluable for testing and debugging because they allow developers to inspect the network traffic generated by an application. By installing a trusted certificate authority on a test device, Charles can perform controlled SSL Proxying, acting as a man-in-the-middle between the app and the server and allowing HTTPS traffic to be decrypted and inspected.

This makes Charles useful not only for finding bugs, but also for demonstrating an important security principle: anything embedded in a client application should be considered potentially accessible to someone who controls that client. An attacker with sufficient access to an application can use techniques such as reverse engineering, instrumentation, or traffic interception to discover how its APIs work and potentially expose sensitive information.

For this reason, avoid embedding long-lived secrets in mobile applications whenever possible. Instead, use appropriate authentication and authorization flows and follow established practices for token management, including OAuth 2.0.

Exploring these scenarios with Charles Proxy in a controlled testing environment helps developers see these risks firsthand and build a stronger understanding of application security.

If you’d like to explore this topic further, I also recommend this insightful article by Aaron Parecki: OAuth 2.0 and API Keys Aren’t Safe in Mobile Apps.

Why Use Charles Proxy?

Charles Proxy is packed with features that make it a powerful tool for developers and testers. In this tutorial, however, we’ll focus on one of its most useful capabilities: capturing and inspecting HTTPS traffic.

Some of the features that make Charles particularly valuable for testing include:

  • SSL Proxying: View encrypted HTTPS traffic in plain text for detailed analysis.
  • Bandwidth Throttling: Simulate slower internet speeds and high-latency conditions to test application performance under different network scenarios.
  • Editing Requests and Responses: Modify requests and responses on the fly to test different inputs, outputs, and application behaviors.
  • Request Repetition: Repeat captured requests to reproduce scenarios and test backend changes.
  • Breakpoints: Intercept requests and responses before they reach their destination, allowing you to modify traffic and test edge cases and error-handling scenarios.
  • AJAX Debugging: Inspect XML and JSON requests and responses in a structured tree view or as plain text.
  • AMF Support: Inspect Flash Remoting and Flex Remoting messages in a readable tree format.
  • Validation Tools: Validate HTML, CSS, and RSS/Atom responses using the W3C validator.

In this tutorial, we’ll put SSL Proxying to work. We’ll configure Firefox to route its traffic through Charles, install the Charles Root Certificate, capture HTTPS communication, and enable SSL Proxying to decrypt and inspect the traffic.

By the end, you’ll have a practical understanding of how Charles sits between the browser and the web server — and how it can make HTTPS communication visible during controlled testing.Getting Started

Installing Charles is straightforward, and it’s available for Windows, macOS, and Linux. While the trial version comes with pop-ups, the paid version unlocks a seamless experience. Setting it up includes installing the Charles Root Certificate to enable SSL proxying and configuring your application or browser to route traffic through Charles.

In this guide, we’ll explore key features like intercepting traffic, enabling SSL proxying, editing requests, all while demonstrating real-world use cases like debugging the popular httpbin.org website.

Let’s get started and unlock the full potential of Charles Proxy for your testing needs!

0. Charles Installation on Ubuntu 24:

My System:

OS: Ubuntu 24.04 LTS
Processor: Intel® Core™ i7–9750H × 12 — 8.0 GiB RAM

docker -v
Docker version 27.3.1, build ce12230

Update your System:

sudo apt-get update

Add the Charles Proxy Repository:

sudo mkdir -p /etc/apt/keyrings

wget -qO- https://www.charlesproxy.com/packages/apt/charles-repo.asc \
| sudo tee /etc/apt/keyrings/charles-repo.asc > /dev/null

echo "deb [signed-by=/etc/apt/keyrings/charles-repo.asc] https://www.charlesproxy.com/packages/apt/ charles-proxy main" \
| sudo tee /etc/apt/sources.list.d/charles.list > /dev/null

sudo apt-get update

Always validate newly added repository configuration files to ensure they have the correct syntax before running apt update.

Avoid using apt-key, as it is deprecated. Instead, use a dedicated keyring file under /etc/apt/keyrings and reference it with the repository’s signed-by option.

Install Charles Proxy

sudo apt-get install charles-proxy5

1.My setup — Firefox on Linux

If you have Firefox installed, Charles may ask whether you have installed the Firefox Add-On. This allows Charles to determine whether the browser is configured to work with the Charles Add-On.

For the current Firefox interface, including Firefox 156.0 (64-bit), you can access the proxy configuration through:

Settings → Privacy & Security → Connection and Software Security → Configure Proxy Access to the Internet

In some Firefox versions, the same settings may appear under:

Settings → General → Network Settings → Settings… → Connection Settings

The exact wording and location may vary slightly between Firefox versions, but both paths lead to Firefox’s proxy configuration settings.

Press enter or click to view image in full size
Here’s my Firefox configuration using 127.0.0.1:8888, the default local proxy address and port used by Charles Proxy.

Once you’ve finished experimenting with Charles, remember to restore your original Firefox proxy configuration. Otherwise, Firefox will continue routing your internet traffic through Charles, which may interfere with normal browsing when Charles is not running.

These options determine how Firefox handles HTTP/HTTPS traffic and whether it should be routed through a proxy. For this Charles Proxy tutorial, understanding the difference between them is important because we’ll explicitly configure Firefox to send its traffic through Charles.

Press enter or click to view image in full size

For Charles Proxy

When Charles is running locally, select:

Manual proxy configuration

Then configure Firefox to use Charles as the local proxy:

HTTP Proxy: 127.0.0.1
Port: 8888

If Firefox provides an option to apply the same proxy settings to HTTPS traffic, enable it so that both HTTP and HTTPS traffic are routed through Charles.

Note: 127.0.0.1 refers to your own computer, while 8888 is Charles Proxy’s default listening port.

HTTP Proxy: 127.0.0.1
Port: 8888

Depending on your Firefox and Charles configuration, you may also need to configure the HTTPS Proxy separately.

If Firefox provides an option such as:

Use this proxy server for HTTPS

enable it and use the same Charles settings:

HTTPS Proxy: 127.0.0.1
Port: 8888

This ensures that HTTPS traffic is also routed through Charles for inspection.

Important: Configuring the HTTPS proxy only routes the traffic through Charles. To actually decrypt and inspect HTTPS traffic, you’ll also need to install and trust the Charles Root Certificate and enable SSL Proxying.

The key difference

Think of it this way:

No proxy
↓
Firefox → → → → → Internet



Manual proxy
↓
Firefox → Charles Proxy → Internet
↑
inspect/modify
traffic

For a Charles Proxy testing tutorial, Manual proxy configuration is the option you want because it makes the routing explicit and predictable.

One caution: Charles can only inspect HTTPS traffic after its Charles Root Certificate is trusted by Firefox; simply configuring the proxy does not by itself decrypt HTTPS traffic.

2. Default Proxy Configuration

In Charles, open the Proxy menu and select Proxy Settings.

Here, you can see the ports configured for the different proxy protocols, including the HTTP Proxy Port and SOCKS Proxy Port.

For this tutorial, we’ll use the HTTP Proxy. Note the configured HTTP Proxy Port, as you’ll need it when configuring Firefox.

In a default Charles installation, this is typically:

HTTP Proxy: 127.0.0.1
Port: 8888

Make sure the port shown in Charles matches the port configured in Firefox.

The host name is 127.0.0.1 (your own computer) or the external address of your computer if you want to access Charles from another computer.

You can then configure your browser or application’s proxy settings with that host name and port.

Installing the Charles Certificate

To inspect HTTPS traffic with Charles, Firefox needs to trust the Charles Root Certificate.

The easiest method for Firefox is to let Charles provide the certificate directly through the browser. With Charles running and Firefox configured to use Charles as its proxy, open:

https://chls.pro/ssl

Firefox should display the certificate import dialog. Select:

☑ Trust this CA to identify websites

Then click OK.

Manual certificate import

If you prefer to download and import the certificate manually, in Charles go to:

Help → SSL Proxying → Install Charles Root Certificate

Then, in Firefox:

  1. Navigate to Settings → Privacy & Security → Certificates.
  2. Click View Certificates.
  3. Select the Authorities tab.
  4. Click Import… and select the Charles Root Certificate file (.pem).
  5. When prompted, select Trust this CA to identify websites.
  6. Click OK.

Note: You only need to trust the certificate for websites. There is no need to select the option to trust the CA for identifying email users for this tutorial.

Press enter or click to view image in full size

Then:

Press enter or click to view image in full size

For your Charles Proxy + Firefox testing setup, select only:

✅ Trust this CA to identify websites

That is exactly what Charles instructs for Firefox.

What the two options mean

OptionWhat it allowsFor Charles testing?

✅ Trust this CA to identify websites

Firefox trusts certificates issued by Charles for HTTPS websitesYes

⚠️ Trust this CA to identify email users

Trusts the CA for S/MIME email certificates, used to authenticate/encrypt email identitiesNoBothEnables both types of trust

Not necessary

Why Charles needs the first one

When SSL Proxying is enabled, Charles acts as a man-in-the-middle proxy. Instead of Firefox receiving the website’s original certificate directly, Charles generates a certificate for that website and signs it with the Charles Root CA.

Get J3’s stories in your inbox

Join Medium for free to get updates from this writer.

For example:

Without Charles:

Firefox → → → → → https://example.com
TLS
example.com's
certificate



With Charles:

Firefox → TLS → Charles → TLS → → example.com
│
└── generates certificate
for example.com
signed by Charles CA

By selecting “Trust this CA to identify websites”, Firefox accepts those Charles-generated website certificates.

What happens if you select “email users”?

It enables the Charles CA to be trusted for S/MIME email certificates as well. That’s a completely different certificate use case. Mozilla distinguishes website/TLS trust from email/S/MIME trust.

It doesn’t give Charles some special ability to read your email just because you checked that box. However, there is no reason to grant the CA that additional trust for a Charles web-debugging exercise.

So choose this

☑ Trust this CA to identify websites
☐ Trust this CA to identify email users

Then click OK.

For your tutorial, I’d explicitly tell readers to select only the first checkbox. It follows Charles’ own Firefox instructions and applies the minimum trust needed for HTTPS web debugging.

Security note: while this CA is trusted, Charles can decrypt and inspect HTTPS traffic that you configure for SSL Proxying. Remove the Charles CA from Firefox when you’re finished with testing if you don’t need it anymore. Charles itself describes this SSL-proxying capability as allowing HTTPS communication to be viewed in plaintext.

Now you can view it:

Press enter or click to view image in full size
Charles generates its own certificates for sites, which it signs using a Charles Root Certificate, which is uniquely generated for your installation of Charles (as of v3.10). You will see a warning in your browser, or other application, when it receives that certificate because the Charles Root Certificate is not in your list of trusted root certificates. If you’re curious about the issuer and other details, click ‘View’.

Done!

4.First Request Test

Now that Firefox is configured to use Charles Proxy, let’s make our first request and see what happens.

Open the following endpoint in Firefox:

https://httpbin.org/anything

This endpoint is useful for testing because it returns information about the request, including headers, parameters, and other details sent by the browser.

Once the page loads, switch back to Charles Proxy and locate the request in the Structure or Sequence view. Select it to inspect the request and response details.

At this stage, you should be able to see the HTTPS request being captured by Charles — even though its contents may still appear encrypted.

That’s exactly what we want to investigate in the next step.

Press enter or click to view image in full size
First, here in my Firefox.

In my Firefox, the endpoint returns an empty JSON response. The certificate is also valid, which is a good sign — it confirms that the HTTPS connection is working correctly.

At this point, Charles is successfully capturing the request, but we haven’t yet enabled SSL Proxying, so the HTTPS payload remains encrypted.

Press enter or click to view image in full size

However, when I inspect the intercepted traffic in Charles, the data still appears encrypted.

See for yourself:

Press enter or click to view image in full size
Press enter or click to view image in full size

Let’s fix this. We’ll ask Charles to enable SSL Proxying, allowing him to act as a man-in-the-middle HTTPS proxy. This will enable us to view the communication between the web browser and the SSL web server in plain text.

Let’s fix this. We’ll configure Charles to enable SSL Proxying, allowing it to act as a controlled man-in-the-middle proxy for HTTPS traffic. This lets us inspect the communication between the web browser and the HTTPS server in plain text.

5. SSL Proxying Setting

In Charles, open:

Proxy → SSL Proxying Settings…

This is where we configure Charles to decrypt HTTPS traffic so that we can inspect the request and response contents during our test.

httpbin.org:443
This will act as a proxy for the https://httpbin.org site.

6. The result

Press enter or click to view image in full size
Press enter or click to view image in full size

The data has now been successfully decrypted. Notice the difference — the two curly braces are now visible:

curly braces are now visible

The data has now been successfully decrypted. Notice the difference — the two curly braces are now visible:

At this point, you should have a clear understanding of the overall picture and how Charles Proxy can help you inspect HTTPS traffic during controlled testing.

You’ve configured Firefox to use Charles, trusted the Charles Root Certificate, captured an HTTPS request, and enabled SSL Proxying to decrypt and inspect the traffic.

That’s all for now, folks!

Try It Yourself

Now that you have Charles Proxy intercepting and decrypting HTTPS traffic, why not experiment a little?

Try these exercises:

  • Inspect another website: Open a different HTTPS website and explore its requests, response headers, and payloads in Charles.
  • Compare HTTP and HTTPS: Observe how the traffic looks before and after enabling SSL Proxying.
  • Inspect httpbin.org: Try different endpoints such as /headers, /ip, or /user-agent and see what information is sent by your browser.
  • Modify a request: Use Charles to change a request parameter or header and observe how the server responds.
  • Try a breakpoint: Pause a request before it reaches the server and inspect or modify it before allowing it to continue.
  • Experiment with throttling: Simulate a slow network connection and see how the website behaves under reduced bandwidth.

These small experiments will help turn the concepts from this tutorial into practical experience — and give you a much better feel for what is happening behind the scenes when your browser communicates with a server.

Remember: Only intercept and modify traffic that you own or are explicitly authorized to test.

That’s all for now, folks! Happy debugging! 🚀

Credits and References

Charles page

Now that you’ve completed Using Charles Proxy for Testing — Tutorial, would you like to read my latest article, Demystifying CORS: Decoding Security Headers on Massive Infrastructure, and learn how to diagnose cross-origin issues, configure server-side headers, and manage trusted domains at scale?

Read the article on Medium →

Additional Annotations

How to Safely and ethically demonstrate Charles Proxy’s capabilities?

there are several safe and legal environments where you can demonstrate Charles Proxy’s ability to intercept HTTPS traffic. These include testing applications, sandbox websites, or controlled environments designed for debugging and learning. Here are some suggestions:

1. Local Development Environment

  • Set up a simple HTTP(S) server on your machine using tools like Flask, Node.js, or any web server.
  • Create an app or API with SSL enabled and use Charles to intercept traffic between your browser or mobile app and the local server.

2. Publicly Available Test Websites

  • Websites like httpbin.org provide endpoints specifically for testing HTTP requests and responses.
  • Use these endpoints to demonstrate intercepting GET, POST, or other HTTP methods.

3. Mock APIs

  • Services like Mocky or Postman Mock Servers let you create mock APIs to test client-server interactions.
  • Set these up and use Charles to observe HTTPS traffic.

4. Controlled Mobile Apps

  • Use your own mobile app or a test app where you control the backend. Ensure SSL proxying is enabled for these.

5. Intentional Vulnerable Systems

  • Platforms like OWASP Juice Shop or DVWA are intentionally vulnerable applications for ethical hacking and debugging.
  • Ensure you’re using them in a controlled, legal setting.

6. Dummy or Demo APIs

Tips for Safe Testing

  • Use a Staging Environment: Set up a replica of production systems for debugging without affecting real users or data.
  • Test on Local Networks: Ensure your interceptions happen within networks you control, avoiding public or shared Wi-Fi.
  • Avoid Sensitive Data: Never test on apps or websites that process sensitive or private user information unless explicitly permitted.

These environments ensure you can safely and ethically demonstrate Charles Proxy’s capabilities.

What this code is doing?

curl -x http://127.0.0.1:8888 https://httpbin.org

The provided command uses curl to make an HTTP request to the URL https://httpbin.org while routing the traffic through a proxy server running on 127.0.0.1:8888. Here’s a detailed breakdown:
Command Breakdown:

curl -x http://127.0.0.1:8888 htpps://httpbin.org

curl:
curl is a command-line tool used to transfer data to or from a server using various protocols (e.g., HTTP, HTTPS, FTP).

-x http://127.0.0.1:8888: This option specifies the proxy server to use for the request.
http://127.0.0.1:8888: 127.0.0.1: Refers to localhost, indicating the proxy server is running on the same machine; 8888: The port on which the proxy server is listening (commonly used by tools like Charles Proxy or Squid).

https://httpbin.org:
This is the target URL that curl will attempt to access.
The request will be routed through the proxy at 127.0.0.1:8888.

— — —

Trobleshooting:

If you configure Charles to act as a proxy and it ends up being misconfigured, you may find that you’re unable to browse any websites. The following message will appear:

Just disable the proxy, and you’re all set!

Visit : https://gitlab.gnome.org/GNOME/seahorse

Seahorse is a project on GitLab, which is a graphical user interface (GUI) for managing encryption keys in the GNOME desktop environment.

Seahorse Overview:

  • Purpose: Seahorse allows users to manage their GPG keys (used for encrypting and signing data), SSH keys (for secure communication), and other cryptographic keys easily. It’s a frontend for the GPG (GNU Privacy Guard) software and integrates with GNOME Keyring, which securely stores passwords and encryption keys.

Main Features:

  • Manage PGP/GPG keys: Seahorse allows users to create, import, export, and delete PGP keys for encrypting and signing messages and files.
  • SSH Key management: It helps in managing SSH keys for secure login to remote servers.
  • Keyring integration: Seahorse integrates with the GNOME Keyring to manage and store passwords and other sensitive data securely.
  • Graphical Interface: It provides a user-friendly interface to handle complex cryptographic operations without needing to use the command line.
  • Use Case: If you’re using encryption for email, file protection, or SSH access on a GNOME-based system, Seahorse simplifies the key management process. It’s particularly useful for people who prefer a graphical interface over command-line tools.

In summary, Seahorse is an essential tool for managing encryption keys securely on GNOME-based systems.

Charles Proxy in 3 Minutes

Press enter or click to view image in full size
Download as Charles Proxy in 3 Minutes.pdf

✨ Updated — September 29, 2026: This tutorial has been refreshed with clearer explanations, updated Firefox/Charles Proxy steps, and improved SSL Proxying guidance. I added the update note to the header of Charles Proxy in 3 Minutes, just below the tech chips.

Curiosity:

The Teapot in Charles Proxy Isn’t Just a Cute Icon 🫖

The HTTP 418 “I’m a teapot” status code is one of the most famous easter eggs in computer science history. It was defined in RFC 2324, an April Fools’ Day joke published on April 1, 1998, by the Internet Engineering Task Force (IETF).

The RFC introduced the Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0), a satirical extension of HTTP designed to manage and control internet-connected coffee pots.

🫖 The Logic Behind the Teapot Response

The 418 status code was specifically designated for an exact scenario: if an internet-connected coffee pot was asked to brew coffee, but it was actually a teapot, it had to refuse the request with 418 I’m a teapot. The short text entity returned in the response body could specify what kind of tea it was brewing.

--

--

J3
J3

Written by J3

Computer Engineer | AI & Data Systems | IoT & Embedded Systems | Product Creator — From Idea to Product | Founder @ Jungletronics & Kidstronics

Jungletronics
Jungletronics

Published in Jungletronics

Education & STEAM Learning by building. Practical explorations in AI, programming, electronics, robotics, IoT, and other STEAM topics — from ideas and experiments to working products. Follow and build with us.