SReverseby Simpa Labs

API Discovery

How to find API endpoints inside an APK

Base URLs hide in the dex, in resources, or behind native code. Endpoints hide behind auth. Here is where to look.

What an APK actually exposes

An APK is a ZIP container, and each kind of file inside it answers a different question. The manifest names the process and the entry point. Compiled resources hold strings and references. DEX files hold the Java and Kotlin bytecode. Native libraries hold the code that runs after a JNI call. Bundled assets can hold certificates, environment files and configuration. When you are looking for a network story you want all of them, because each one can hold a piece that the others do not.

The first step is to split the package and produce a readable view that you can search.

unzip -o app.apk -d apk
apktool d app.apk -o out
jadx -d out app.apk

Jadx gives you decompiled source you can read and follow. Apktool gives you a resource and Smali view that preserves things the decompiler hides. You usually want both.

Search every layer for the endpoint

Run the same search over the resources, the DEX strings and the native libraries. A base URL, a path fragment, a scheme name or a certificate filename are each a hit. The point is to find where each one is referenced so you can go read the code that uses it.

grep -aohE 'https?://[A-Za-z0-9._/:?&=%-]+' apk/resources.arsc 2>/dev/null | sort -u
grep -rnoE 'https?://[^[:space:]"']+' out/sources 2>/dev/null | sort -u
strings lib/arm64-v8a/libapp.so 2>/dev/null | grep -oE 'https?://[^[:space:]]+' | sort -u

A hit is evidence that a string exists, not that a request uses it. A route in the DEX may be built from parts, a host from remote configuration, a path from a variable. Treat every hit as a lead and confirm it against the code that builds the request.

Read a hit as a lead

Where you found itWhat it provesWhat to do next
resources.arsc or strings.xmlA base URL is shipped as a resource.Find the code that loads it, then the request that consumes it.
A DEX stringThe app builds the path in Java or Kotlin.Read the request builder and the values interpolated into the path.
A native library stringThe path or host is built in native code.Trace the JNI call that returns it, and the encoding it uses.
A GraphQL operation nameThe app uses a GraphQL endpoint.Match the operation to a query or a persisted-query hash.
A WebSocket scheme or certificate fileThe app uses a live connection or a pinned cert.Plan for a persistent socket or a pinning bypass at capture time.

Find the request builder, then the interceptor

Retrofit interfaces are the easiest to read because the annotations preserve the shape: the path, the HTTP method and the header names are all in the signature. What they do not preserve is the work done per call. An OkHttp interceptor adds a token, a timestamp, a nonce, a signature or a device header to every request, and that is usually the hard half of the reconstruction.

# which classes build requests
grep -rloE '@(GET|POST|PUT|DELETE|PATCH)' out/sources | sort -u
# which classes change the request per call
grep -rloE 'okhttp3.Interceptor|okhttp3.OkHttpClient|Interceptor.Chain' out/sources | sort -u
# the Ktor, Volley or raw names, if the app does not use OkHttp
grep -rloE 'KtorClient|Volley|HttpURLConnection' out/sources | sort -u

Follow each candidate to the method that builds the Request. That method is where you see the base URL, the path, the body and the headers actually assembled. The interceptor that sits on the client is where you see the values added at send time.

Record the flow, not a list of URLs

An endpoint list is not a usable API. For each call record the method, the exact path, the query order, the body encoding, the required headers, the cookie jar, the token source and the request order. Request order is not cosmetic. A refresh interceptor can retry a call after replacing the token, which means the same business action sends two different requests. A configuration call can supply a second hostname. A timestamp and a nonce are often generated seconds before the request and included in a signature.

Missing any one of those dependencies makes a copied request fail, and the failure usually points at the wrong thing because it is an HTTP error rather than a missing-value error.

Confirm outside the app

Static analysis shows what the app can do; runtime observation shows what it did on one tested path. Use both. To confirm, rebuild the sequence with a cookie jar, serialise the body exactly as the app does and refresh through the same call the app uses. When the server returns 401 or 403, compare the generated request byte by byte before changing headers at random.

The output you want is a repeatable call with known inputs and stable error handling, not a longer list of captured requests.

Reviewed 30 August 2026 · SReverse research desk

Relevant capability

APK to API service

Start a project

Send the full APK

Send the full APK. We review the application and quote its complete API reconstruction.

Projects start at $120. Most are delivered in 24 to 72 hours.

Start your full APK reconstruction

Send the full APK

Projects start at $120. Choose WhatsApp or email, then attach the APK in the app that opens. We reply within one hour with the next step and send the fixed quote after review.

Want us to contact you?