Skip to main content

Command Palette

Search for a command to run...

๐Ÿ“ก Capture Your Mobile Applicationโ€™s Network Logs from Automation โ€“ Part 2

How to Use MITM Proxy and Java for Network Log Interception

Updated
โ€ข5 min read
๐Ÿ“ก Capture Your Mobile Applicationโ€™s Network Logs from Automation โ€“ Part 2

๐Ÿ”„ Recap: What We Did in Part 1?

In Part 1, we successfully set up MITM Proxy to intercept network requests from a mobile app running on an Android/iOS device. We learned how to:

โœ… Install MITM Proxy and start a proxy server.
โœ… Configure proxy settings on a real device/emulator.
โœ… Intercept HTTP & HTTPS requests using a MITM CA Certificate.

๐Ÿš€ That was fun, but now letโ€™s take it to the next level!

๐Ÿ”ฅ Whatโ€™s Next?

We donโ€™t just want to view network logsโ€”we want to capture them programmatically in our automation framework.

And for that, weโ€™ll use MITM Proxyโ€™s Java Client!


๐Ÿค– What is the MITM Proxy Java Client?

The MITM Proxy Java Client (mitmproxy-java) acts as a bridge between MITM Proxy and your Java-based automation framework.

๐Ÿ’ก Hereโ€™s how it works:

โœ… MITM Proxy starts a WebSocket server.
โœ… A Python plugin inside MITM Proxy sends network traffic to the Java client.
โœ… The Java client captures and stores network requests for analysis.

With this setup, we can:
๐Ÿ” Capture API calls made by the mobile app.
๐Ÿ“„ Save network logs for debugging.
๐Ÿ”— Attach logs to test reports.

โš™๏ธ Step 1: Install the Required Dependencies

๐Ÿ“Œ Prerequisites

Before setting up the Java client, make sure you have:

1๏ธโƒฃ MITM Proxy v9+ installed and working.
2๏ธโƒฃ Python 3.6+ (MITM Proxy uses async WebSockets).
3๏ธโƒฃ WebSockets module installed:

pip3 install websockets

๐Ÿ“Œ Add MITM Proxy Java Dependency to Your Project

If youโ€™re using Maven, add this dependency to your pom.xml:

<dependency>
  <groupId>io.appium</groupId>
  <artifactId>mitmproxy-java</artifactId>
  <version>2.0.2</version>
</dependency>

๐Ÿšจ Note: The latest version is not yet available in the official repository, so you may need to clone the source code and build your own JAR.

๐Ÿ“‚ Step 2: Integrate MITM Proxy Java Client in Your Framework

๐Ÿ•’ Step 2.1: Create a Class to Store Intercepted Messages

To store network logs with timestamps, create InterceptedMessages.java:

import io.appium.mitmproxy.InterceptedMessage;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

import java.util.Date;

/**
 * Stores intercepted message along with timestamp.
 */
public class InterceptedMessages {
    @Accessors(chain = true)
    @Getter@Setter
    private Date timestamp;

    @Accessors(chain = true)
    @Getter@Setter
    private InterceptedMessage interceptedMessage;
}

๐Ÿš€ Now every intercepted request will be saved with a timestamp!


๐Ÿ›  Step 2.2: Add a Handler to Start & Stop MITM Proxy

Now, letโ€™s create MITMProxy.java to:
โœ… Start the proxy listener.
โœ… Capture network traffic.
โœ… Stop the proxy when needed.

import io.appium.mitmproxy.InterceptedMessage;
import io.appium.mitmproxy.MitmproxyJava;
import lombok.Getter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeoutException;

/**
 * MITM Proxy Utility for Capturing Network Logs in Automation Framework.
 */
public class MITMProxy {
    @Getter
    private final List<InterceptedMessages> networkCalls = new ArrayList<>();

    private static MITMProxy proxyInstance = null;
    private MitmproxyJava proxy;

    // Singleton Pattern to Ensure Single Instance
    private MITMProxy() {
        startProxyListener();
    }

    public static MITMProxy getProxy() {
        if (proxyInstance == null)
            proxyInstance = new MITMProxy();
        return proxyInstance;
    }

    /**
     * Starts MITM Proxy and Listens for Network Traffic
     */
    private void startProxyListener() {
        System.out.println("๐Ÿš€ Starting MITM Proxy Listener...");

        List<String> extraMitmproxyParams = Arrays.asList("--showhost", "<domain-name-filter>");
        int mitmproxyPort = 8090;

        this.proxy = new MitmproxyJava(getMitmDumpPath(), (InterceptedMessage message) -> {
            InterceptedMessages interceptedMessage = new InterceptedMessages()
                    .setTimestamp(new Date())
                    .setInterceptedMessage(message);
            networkCalls.add(interceptedMessage);

            // Log each intercepted message
            System.out.println("๐Ÿ” Captured Network Request at: " + interceptedMessage.getTimestamp());
            System.out.println("๐Ÿ“ก Request Details: " + message);

            return message;
        }, mitmproxyPort, extraMitmproxyParams);

        try {
            // Kill existing process on the same port if running
            String processId = ProcessExecutor.executeCommandSync("lsof -t -i:" + mitmproxyPort + " -sTCP:LISTEN").trim();
            if (!processId.isEmpty())
                ProcessExecutor.executeCommandSync("kill -9 " + processId);

            this.proxy.start();
        } catch (IOException | TimeoutException e) {
            throw new RuntimeException("โŒ Failed to Start Proxy: " + e.getMessage());
        }

        System.out.println("โœ… Proxy Listener Started Successfully!");
    }

    /**
     * Retrieves MITM Dump Path
     */
    private String getMitmDumpPath() {
        String result = ProcessExecutor.executeCommandSync("whereis mitmdump");
        return result.split("mitmdump: ")[1].split(" ")[0].trim();
    }

    /**
     * Stops MITM Proxy
     */
    public void stopProxyListener() {
        System.out.println("๐Ÿ›‘ Stopping MITM Proxy Listener...");
        try {
            this.proxy.stop();
        } catch (InterruptedException e) {
            throw new RuntimeException("โŒ Failed to Stop Proxy: " + e.getMessage());
        }
        System.out.println("โœ… Proxy Listener Stopped Successfully!");
    }

    /**
     * Prints All Captured Network Logs
     */
    public void printCapturedLogs() {
        System.out.println("๐Ÿ“œ Printing Captured Network Logs...");

        if (networkCalls.isEmpty()) {
            System.out.println("โš ๏ธ No network requests were intercepted.");
            return;
        }

        for (InterceptedMessages msg : networkCalls) {
            System.out.println("โณ Captured Request at: " + msg.getTimestamp());
            System.out.println("๐Ÿ“ก Request Details: " + msg.getInterceptedMessage());
            System.out.println("--------------------------------------------------");
        }
    }
}

๐Ÿ”ฅ What Does This Class Do?

โœ… Automatically starts MITM Proxy when called.
โœ… Captures every intercepted request and stores it with a timestamp.
โœ… Prevents port conflicts by killing any existing process on the same port.


๐Ÿš€ Step 3: Start Capturing Network Logs

๐ŸŽฌ Start the Proxy

MITMProxy.getProxy();

๐Ÿ‘‰ This starts the MITM Proxy and begins capturing network requests.


๐Ÿ“„ Fetch Intercepted Logs

networkLogMessage = MITMProxy.getProxy().getNetworkCalls();

๐Ÿ‘‰ This retrieves all captured network logs, which can be saved or attached to reports.


๐Ÿ›‘ Stop the Proxy

MITMProxy.getProxy().stopProxyListener();

๐Ÿ‘‰ This stops the proxy when tests are complete.


๐Ÿ” Verifying Captured Logs

Once your tests have run, print the captured logs to verify that requests are being intercepted:

for (InterceptedMessages msg : MITMProxy.getProxy().getNetworkCalls()) {
    System.out.println("Captured Request at: " + msg.getTimestamp());
    System.out.println("Request Details: " + msg.getInterceptedMessage());
}

๐ŸŽ‰ Now you can capture and analyze every network request in your tests!


๐ŸŽฏ Whatโ€™s Next?

โœ… We can now intercept API calls from our mobile automation framework! ๐ŸŽฏ

But what if we need to store these logs for later analysis? ๐Ÿค”

๐Ÿ‘‰ In Part 3, weโ€™ll:
โœ… Save network logs to files for debugging.
โœ… Attach logs to automation test reports.
โœ… Filter out unwanted noise from logs.

Stay tuned for Part 3! ๐Ÿš€๐Ÿ”ฅ

๐Ÿ’ฌ Questions? Drop a comment below!

More from this blog

T

The Code Console by Himanshu Nikhare | Software Development, Automation, and Tech Insights

25 posts

A curious builder on a journey to turn ideas into code. Learning by doing, debugging through chaos, and crafting solutions one experiment at a timeโ€”because every build starts with a console.log.