How to use Charles Proxy in Xamarin to capture network traffic (including SSL)


Capturing network traffic between your application and your server is a handy way of checking and debugging the data you are sending and what comes back from the server. Charles Proxy shows network calls in a sequence or as a tree structure, including headers and all kind of http information like response times and payload size. It even allows you to simulate adverse network conditions and throttling, ie: an unstable 3g connection.

I´ve been doing this forever on web development so I tried on mobile by configuring a proxy on Android emulators according to some detailed tutorials out there.

Result: None of the tutorials worked with my Xamarin app

Well, actually those tutorials work 😜 but Xamarin needs an additional piece of code. As I don´t want to replicate wonderful posts from other developers, I recommend you follow this specific tutorial step by step: The Android Emulator and Charles Proxy: A Love Story. It´s a bit long but hey, you only need to do it once!

Xamarin specific bits: writting a custom HttpClientHandler

I´ve been pulling my hair big time because the tutorial didn´t work, until I tried by manually pointing to Charles Proxy from the app code.

First of all, check your local ip and charles port.
On Charles, click menu > Local IP addresses:

Then go to menu > Proxy > Proxy settings… to check the default port:

Setup the proxy with a custom HttpClientHandler:

var handler = new HttpClientHandler
{
    // local ip, charles port
    Proxy = new WebProxy("192.168.0.52", 8888) 
};

Then use it whenever you create an HttpClient in your app

var client = new HttpClient(handler);
// TODO: make some requests to test charles!

At this point everything should work and you should be able to observe all network traffic. For the shake of your mental health, make sure you only do this on debug mode and it never gets to production.

Bonus

Beware that your app stops working if your HttpClientHandler is pointing to Charles but Charles is not running. To tackle this issue I personally use an environment variable that I can set to false when I´m not debugging network traffic:

// http proxy
if (Environment.GetEnvironmentVariable("UseHttpProxy") == "true")
{
    var handler = new HttpClientHandler
    {
        Proxy = new WebProxy(
            Environment.GetEnvironmentVariable("ProxyHost"), 
            int.Parse(Environment.GetEnvironmentVariable("ProxyPort") 
                ?? throw new InvalidOperationException()))
    };

    _client.SetHandler(handler);
}

To set env variables on Android, you have to create a text file in your Android project root, call it env.txt (it can be any name) and set its Build Action to AndroidEnvironment:

Related Posts

Fixing push notifications on Android 8. Aka channels

Android 8 adaptative (vector) icons

UIStackView magic

When Apple realized a LinearLayout could be useful for developers...

Getting fancy with UIView anchors and state changes

A simple page-indicator for your android view-pager

A bit of xml and C#. No 3rd party libs required

Large file downloads on Windows 10 mobile

Download safely in the background with progress feedback

UWP mobile side loading

SQLite.NET > async VS sync

Or how we (developers) love to complicate our code base

Making iOS forms usable

Prevent user frustration by implementing good practices with Xamarin.iOS

Easy and cross-platform localization (Xamarin & .NET)

Share locales from a PCL. Get up and running in no time