Skip to Content
Managed Emulators

Managed Emulators

Some data only lives inside a mobile app — there’s no website, or the app talks to its servers in a way a normal HTTP client can’t reproduce. Managed Emulators lets you scrape those apps, including your own, by running them on real Android devices we host for you.

You don’t install anything, set up a device, or manage proxies. You upload the app you want to run, then from your spider you ask for it on a device in the country you want, and you get normal responses back — just like scraping a website.

Emulators works on its own, or together with Personas and Storage for the “log in once, reuse forever” workflow below.

Bring your own app (upload an APK)

The devices start as a clean Android phone with no apps installed, so the first step is to upload the app you want to run. This is how you load your own app to inspect it, or any app you have the right to automate.

Upload an APK against the Emulators add-on (the Storage add-on must also be enabled — your uploads live in your own private storage bucket):

POST /api/v1/me/emulators/apps (multipart/form-data) apk the .apk file (required) package_name e.g. com.example.myapp (required) version e.g. 3.1.70 (required) label a friendly name (optional) frida a custom Frida script (optional — see below) splits one or more split APKs (optional, for App Bundles) obb one or more .obb files (optional, expansion assets)

Each upload is stored under its package and version, and the newest upload of a package becomes the latest for that package. List or remove what you’ve uploaded:

GET /api/v1/me/emulators/apps # your app catalog DELETE /api/v1/me/emulators/apps/{package}/{version} # remove one version

You can upload and manage apps from the Emulators section of the dashboard — a point-and-click uploader with a catalog of what you’ve uploaded — or call the endpoints above directly.

When a session names an app you’ve uploaded, the platform installs it on the device automatically (App Bundles with split APKs and OBB expansion files are installed too) before your first request runs.

Choosing where traffic comes from

Every request from the device goes out through the proxy you choose. Pick the proxy type and country per session:

  • proxydatacenter (default, fast and cheap) or residential (a real home IP, harder to block).
  • country — a 2-letter code like us, mx, or br.

Every session keeps one consistent IP for its whole lifetime, so an app sees a stable, believable connection rather than an address that jumps around.

Using it from a spider

When your project has the Emulators add-on enabled, the platform injects the connection details into your job automatically. Set app to the package name you uploaded, tag a request for the emulator, and you get a normal Scrapy response — the request runs through your app on a real Android device on the proxy and country you chose:

import scrapy class PricesSpider(scrapy.Spider): name = "prices" def start_requests(self): yield scrapy.Request( "https://api.example.com/products", meta={ "emulator": { "app": "com.example.myapp", # a package you uploaded "proxy": "residential", "country": "mx", } }, callback=self.parse, ) def parse(self, response): for item in response.json()["items"]: yield {"id": item["id"], "price": item["price"]}

That’s the whole integration. You write your spider as usual; the device runs your app, makes the request, and hands you back the response to parse. The response carries the status, body, and headers back, so response.headers (content type, any Set-Cookie, and so on) is available in your callback just like a normal fetch.

The first session of the day may take a couple of minutes while the device images warm up; sessions after that open in around 20 seconds.

Pinning an app version

By default a session installs the latest version you uploaded for a package. To reproduce a run against a specific build, pin it with app_version:

meta={"emulator": {"app": "com.example.myapp", "app_version": "3.1.70", "proxy": "residential", "country": "us"}}

Uploading a newer version doesn’t change pinned runs — it only moves what “latest” points to.

Custom Frida scripts

Some apps need an on-device tweak to automate — bypassing certificate pinning, adjusting a request signer, or hooking a specific method. Upload a Frida script alongside the APK (the frida field above) and it’s loaded into your app when the device starts.

The script is scoped to your app on your own isolated device — it never touches another device or another customer. A default anti-detection layer is always applied; your script runs on top of it. Omit it entirely and the app runs with just the defaults.

Log in once, reuse forever

The slow part of mobile scraping is signing in — many apps need a phone number, an SMS code, or a captcha. The goal is to do it once:

  1. Open the device in your browser. From the dashboard you get a live screen you can tap and type on, just like holding the phone. Sign into the app by hand.
  2. Save the profile. Click Save profile and the app’s signed-in state is stored against a persona — a reusable identity you own.
  3. Reuse it at scale. Later, load that persona onto a fresh device and the app is already signed in. No re-login, no new SMS code.

A persona keeps the same device identity every time you load it (a consistent phone model and fingerprint), so the app sees the same trusted device across runs.

Finding a saved profile

Once you’ve saved a profile, your spider can look up which personas already have a signed-in copy of an app. The platform injects a job-scoped token, so there are no credentials to manage:

GET /api/v1/crawler/personas?app=com.example.myapp

You can also filter by any label you’ve added to a persona:

GET /api/v1/crawler/personas?tag=us-shoppers

Pass the persona you want into the emulator request and the device loads it before running your request:

meta={"emulator": {"persona": persona_id, "app": "com.example.myapp", "proxy": "residential", "country": "us"}}

What the platform handles for you

  • Installing and running your app on a genuine Android device (including App Bundles with split APKs and OBB assets).
  • Anti-detection — the device presents as a real phone.
  • Proxying every request through your chosen type and country, on one steady IP.
  • Signed-in sessions — saved profiles restore the login so you don’t sign in again.

You upload your app, choose the proxy and country, and parse the results.

Last updated on