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.
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.
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.
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.
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.
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 theios 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
Roolink answers 400 or 422 on the sensor call
Roolink answers 400 or 422 on the sensor call
error field. The usual causes are an app key that is not enabled on your account, a proxy URL without a scheme, or a deviceId from the other platform.Roolink answers 429
Roolink answers 429
The app's server blocks the request
The app's server blocks the request
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 connection fails or falls back to HTTP/1.1 in Python or Node
The connection fails or falls back to HTTP/1.1 in Python or Node
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.The device disappears between runs
The device disappears between runs
deviceId regularly to keep it alive, and expect to start fresh after a long pause. See Sessions.