Skip to main content

๐Ÿ“ก 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 readMarkdown
๐Ÿ“ก 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!

About the author

  • I am a Senior Software Engineer at BigBasket with over three years of experience in software development. Specializing in QA automation, CI/CD, and mobile automation, I am passionate about creating efficient workflows and sharing knowledge through blogs and articles.

    I actively contribute to the tech community through my work, open-source projects, and insightful content. Feel free to connect with me on GitHub or LinkedIn to explore my projects and contributions.

No comments yet. Be the first to comment.

More from this blog