Mobile App Scraping: Logged In, Token Valid, Not a Person

Sebastian Sztemberg

Sebastian Sztemberg

Managing Partner, Mobile

Your API logs look fine. That’s the problem with mobile app scraping.

95.8% of API attack attempts come from authenticated sources, according to Salt Security’s latest State of AI and API Security report. These are valid tokens, valid sessions, valid TLS handshakes, making requests that pass every check you built. Mobile app scraping detection comes down to noticing a logged-in, token-valid client that happens to be a script instead of a person.

Nobody builds for that. You built auth to keep people out. You didn’t build anything to notice when the “people” getting in aren’t people.

What Mobile App Scraping Detection Actually Means

Screen scraping is dead for anyone serious. Parsing HTML, waiting for render, fighting CSS selectors — slow, brittle, expensive to maintain. Your mobile app doesn’t have that problem for the attacker. It hands them structured JSON on a silver tray.

Imperva’s 2025 Bad Bot Report puts it plainly: 44% of advanced bot traffic now targets APIs directly, versus 10% hitting traditional web frontends. The shift already happened. If your detection strategy is still “watch for scrapers on the website,” you’re defending the door nobody’s using.

mobile app scraping detection in numbers

Mobile app scraping detection means something specific: identifying when a client calling your API is not the app you shipped, running the way you expect, used by a person doing what people do.

The Attack Chain Behind Every Mobile App Scraping Detection Gap

Here’s what it actually costs someone to pull your pricing, your inventory, or your catalog out of your app. Assume no hardening beyond default React Native or native builds.

  1. Pull the binary. Download the APK from your own phone or a mirror. Cost: $0. Skill: tap install, copy the file.
  2. Decompile it. JADX for Java/Kotlin. For Hermes bytecode — which most production React Native apps ship — hermes-dec, if it supports your bytecode version. If it doesn’t, the string table still lists your URLs. Cost: $0. Skill: run a tool, read the output.
  3. Map the endpoints. Grep for the base URL. Read the auth headers. Find the token refresh flow. Cost: $0. Skill: ctrl+F.
  4. Bypass pinning, if it exists. Runtime instrumentation can patch certificate checks in memory. Public tooling makes this cheaper than most teams assume. Cost: $0, maybe a $20 used Android phone. Skill: follow an existing walkthrough.
  5. Replay outside the app. Automate the copied request pattern. Rotate through residential proxies if you want to look like real traffic — Imperva found 21% of bot attacks routed through ISP networks ran through residential proxies. Cost: a $50/month proxy subscription. Skill: basic scripting.

Five steps. Four of them are free. The expensive one is a monthly subscription cheaper than your Slack bill.

If you shipped Hermes with zero additional hardening, step 2 took someone ten minutes, not ten hours. Decompilers lag behind every new bytecode version, but scraping doesn’t need a full decompile. The strings are readable. The variable names are gone, but the string constants and your endpoint URLs are sitting right there.

Why Mobile App Scraping Detection Fails at the Dashboard Level

Every step above produces traffic that looks legitimate to a standard monitoring setup. Valid token. Valid TLS session (once pinning is bypassed, the handshake itself is clean). Requests shaped exactly like the mobile client would send them, because the attacker copied the client’s own request format.

Three specific reasons your current setup won’t flag it:

  • IP-based rate limiting doesn’t work against distributed proxies. You’re blocking by IP. The attacker rotates IPs faster than your block list updates.
  • Per-session limits don’t catch per-account abuse spread across many accounts. Create 500 free accounts, query each one 10 times, and no single session trips anything.
  • Nobody’s watching the ratio between API calls and UI events. A real user who hits the pricing endpoint 40 times in an hour also generated 40 screen views, 40 taps, scroll events, maybe a cart add. A scraper hits the endpoint 40 times and generates zero UI telemetry, because there’s no UI involved.

That third one is the actual signal. Most teams don’t collect it because nobody thought to ask for it until the business impact already showed up somewhere else.

Same token. Same 200 OK. One of them is a script.

Drag through one hour of two logged-in sessions. Watch the API side, then the app side.

One hour Minute 0
Drag me
0 min60 min
0
Session A · UI events
0
Session B · UI events
Same token. Same requests. Same 200 OK.
Check what your API can’t see →

What's Actually Being Scraped

Attackers scrape whatever your API exposes that has resale or competitive value. The target shifts by vertical, but the economics are the same everywhere: your live data is worth more to a competitor than the cost of extracting it.

App TypeWhat Gets PulledWhat It Costs You
Travel / bookingFares, routes, seat availabilityAlgorithmic undercutting within hours of your price change
MarketplaceListings, seller data, inventory depthA cloned competing marketplace built on your supply data
FintechRate quotes, loan terms, public transaction dataArbitrage, competitive quote matching, fraud probing
E-commerceSKU catalog, stock levels, pricingMargin compression, fake "out of stock" from cart-holding bots
On-demand / deliveryDriver density, zones, ETA logicOperational intelligence leak, targeted supply poaching

Imperva's industry breakdown backs the travel row specifically: travel became the most attacked sector in 2024, with simple bots behind 52% of the attacks on it, and fare scraping named among its main threats. Financial services draws 40% of all bot attacks on APIs, more than any other industry, for the same reason — rate and quote data is worth extracting in real time.

The Defense Stack, and the Part Nobody Admits

Every layer below does something. None of them do everything. If a write-up tells you one of these solves mobile app scraping detection on its own, that write-up is selling you the layer.

App Attestation

Google Play Integrity and Apple App Attest solve a real problem: an API key proves who's asking, but nothing about what's asking. A stolen token replayed from a Python script looks identical to the token used by your real app — unless you can cryptographically verify the request came from an unmodified binary on a legitimate device.

That's what attestation does. The backend issues a nonce, the device asks the OS for a verdict, the OS checks signature, install source, and hardware state, and hands back a signed token you validate server-side.

mobile app scraping detection attestation flow

What it doesn't do: survive a fully compromised device. Modules like TrickyStore inject spoofed keybox data specifically to trick Play Integrity into returning a clean verdict on a rooted phone. It's also rate-limited — Play Integrity defaults to 10,000 requests per day on the standard tier, which means you can't attest every single high-frequency call without paying for more quota or architecting around it.

Certificate Pinning

Pinning stops the easy version of a man-in-the-middle attack — a proxy with a self-signed cert that the OS would normally reject, elevated to trusted status on a rooted device. Without pinning, that's a two-minute setup for anyone with Burp Suite.

What it doesn't do: survive Frida. A hook into the running process patches the certificate validation function before the network call ever fires. The app never knows the check was skipped. This is the step 4 from the attack chain above — it's not hard, and it's publicly documented.

Pinning raises the bar from "anyone with a proxy app" to "anyone who can run a Frida script they didn't write." That's a real increase in attacker cost.

Rate Limiting

The global, IP-based version already lost to proxy rotation above. Endpoint-specific, behavior-scored limiting works better — the search endpoint gets a different threshold than the login endpoint, and the threshold adjusts based on account history, not a flat number.

What it doesn't do: distinguish a scraper querying slowly on purpose from a real user browsing a lot. Attackers who've been burned before throttle themselves deliberately to stay under the radar, so a rate limit only stops the ones who haven't been burned yet.

Behavioral Telemetry

This is the layer that actually produces a usable signal. It's also the one most teams skip. There's no library to install here. You build the instrumentation yourself.

An account querying your pricing endpoint 500 times with zero screen-view events, zero scroll events, and perfectly even 200ms intervals between calls is not a person. A real session has jitter, abandoned flows and UI noise.

What it doesn't do: work out of the box. You need the telemetry pipeline instrumented before you have the data to score against.

mobile app scraping detection defense layers

Building Mobile App Scraping Detection That Actually Signals

The four inputs to a risk score, roughly in order of how fast they produce signal:

  • Request-to-UI-event ratio per session. The single highest-value metric. Cheap to compute once you're logging both sides.
  • Pagination and query-depth abuse. Real users rarely page past result 3. Scrapers walk the entire result set in order.
  • Timing uniformity. The 200ms metronome from above. Easy to catch, and the first thing a careful attacker jitters away.
  • Query-to-conversion ratio by account. An account that searches constantly and never books, buys, or completes anything is either a lurker or a scraper. At volume, it's almost always the latter.

None of these require blocking anything immediately. They require logging, then scoring, then a human reviewing the score before anything gets throttled. The signal only means something once it's measured against your own traffic over time.

What Not to Do When You Suspect Scraping

  • Don't block entire countries on a hunch. You'll cut off real customers and the attacker will route around it in an afternoon.
  • Don't drop a blanket rate limit across every endpoint. You'll hit your power users before you hit the scraper.
  • Don't rely on CAPTCHA as the only gate. Mobile API calls rarely go through a CAPTCHA-friendly flow, and solver services exist specifically because CAPTCHA alone stopped being a real barrier years ago.
  • Don't treat obfuscation as a substitute for server-side validation. Obfuscating the client makes step 2 of the attack chain slower. It doesn't make step 5 impossible.
  • Don't wait for legal review before you start logging. Evidence collection and detection instrumentation should start immediately — the legal question is separate from the "can we see it happening" question, and the second one is cheaper to fix.

The Part Nobody Likes to Admit

None of this makes your API unscrapable. That's not the goal, and anyone promising it is selling theater. The goal is the attacker's math: raise the cost and the skill required past the point where your data is worth the effort relative to an easier target.

A rooted phone and a free evening gets someone your endpoints today. Attestation, pinning, and endpoint-specific throttling don't change that fact. What they change is how long "today" takes, and how many of the five attack-chain steps require actual skill instead of a copy-pasted script.

If your current monitoring can't tell the difference between a power user and a scraper, assume you're being scraped. How long have you been paying for the infrastructure to serve data to someone who was never going to convert?