Skip to main content

What you will build. A small program that asks Roolink for a mobile device and its sensor, connects to the app’s servers the way that phone would, and makes one request that Akamai accepts. Along the way you keep the device so you can use it again.

What you need. A Roolink account with an API key, the app key for your target app, a residential proxy that keeps the same IP for a session, Python, Go or Node, and a capture of the real app’s traffic so you can copy its headers.

1Set up

Put your Roolink key, your app key and your proxy in environment variables. Install the Roolink SDK and a TLS client, then get the Roolink TLS profiles: a Go module for Go, and a profiles.json file for Python and Node. Both live in the same repository, roolinkio/tlsprofiles.

Before you write code, record the real app once. Run the app on a phone routed through powhttp and perform the request you want to automate. You will copy its headers, in order, in step 4.

2Ask Roolink for a device and a sensor

One call does both. Send the app key, the proxy and the language you want the phone to have. Roolink initializes a device, runs Akamai’s SDK handshake through your proxy, and returns the sensor plus everything about the device it emulated: the iOS version, the hardware identifier, the screen size, the cookies the SDK collected, and the deviceId.

Leave android unset for an iPhone. Set android: true for an Android device or ipad: true for an iPad.

You should see a response with a long sensor string, an ios version such as 26.2, and a deviceId.

3Connect like that phone

Create a client with the TLS profile for the device’s iOS version, the same proxy you gave Roolink, and the cookies from the response. Use the Standard profile first; the TLS profiles page explains when to switch to Secondary.

The proxy must be the same one. Roolink ran the SDK handshake through it, so Akamai already associates this device with that IP.

In Python and Node the profile is an entry from profiles.json, passed as a custom TLS client. The profiles fix the extension order themselves, so leave randomization off, and disable HTTP/3, which the app never uses.

4Make the app’s request

Build the request the app made in your capture: same URL, same headers, same order. Put the sensor in the X-acf-sensor-data header. Wherever the app’s headers describe the phone, use the values from the response instead of the ones in your capture: the OS version, the hardware identifier, the app version, the screen size. The device Roolink emulated and the device your headers describe must be the same phone.

You should see the response a real user would get. An Akamai block usually arrives as a 403 or a 429 with an Akamai reference in the body.

5Keep the device

Save the deviceId, the cookies and the proxy URL together. Next time, pass the deviceId to /sensor and Roolink continues the same device: faster, and with a fingerprint Akamai has already seen. Keep using one device until the app blocks it, then start a fresh one. Sessions explains what belongs together and how long a device lives.

The complete file

The helpers pick the TLS profile from the ios version and copy Roolink’s cookies into the client. In Python, AppSession also adapts the library’s custom-client payload to the current shared library; TLS profiles explains why.

If something goes wrong

Work through these in order. Same proxy for Roolink and for the app request. TLS profile matches the ios version, and you have tried the Secondary variant. Headers match your capture in order, and the device values in them come from the response. Cookies from the response are in the client. Sensor is fresh: generate a new one for each protected request.
The profile did not apply. In Node, confirm customTlsClient is set and withRandomTLSExtensionOrder is false. In Python, confirm you construct the client through AppSession and not tls_client.Session directly. A fingerprint echo such as https://tls.peet.ws/api/all should report h2 and a JA4 that starts with t13d.
Devices are cached for a limited time after each use. Pass the deviceId regularly to keep it alive, and expect to start fresh after a long pause. See Sessions.

Next steps

SessionsWhat makes up a device session, how long it lives, when to reuse and when to rotate.
TLS profilesStandard and Secondary, per iOS version, in Python, Go and Node, and the Android profile.
API referenceEvery field of the sensor request and response.