x-cloud-tracing-uuid response header before changing configuration.
Find the failing step
The browser will not start
A401 not_authorized usually means the API token is absent or invalid. Send it as X-Cloud-Api-Token and use the base URL assigned to your account. A namespace_not_allowed error means the request reached a host that does not serve the account.
Use
"tier": "shared" for testing and "tier": "premium" for production; see choosing the tier. The shared tier accepts only country targeting, and other targeting or session fields return 422 validation_error with the message the shared tier targets 'country' only.
For other 422 validation_error responses, inspect data for the field that failed.
See errors for the full code list. Avoid retrying a timed-out start without checking whether it created a browser.
The site is blocking you
Confirm that you received a block or challenge page. HTTP200 alone does not prove that the expected content loaded.
Start with the proxy
Compare the same small test through another suitable proxy while keeping other settings unchanged. Check the exit country, connection type, and whether the IP changes during a session. A residential or mobile IP may behave differently from a datacenter IP, but no proxy type guarantees access. If the job runs on"tier": "shared", switch to "tier": "premium" before comparing other settings. Keep the IP stable when the site ties a login or challenge to it. More restrictive targeting can reduce availability; see proxies.
Check fingerprint overrides
Remove unnecessary overrides and retest. If you set language, timezone, user agent, screen, or device fields manually, make sure they describe the browser you intend to use. See fingerprints.Tune the fingerprint
If the block persists with default settings, try another OS. Some sites treat desktop and mobile traffic differently, and a fresh profile with a different device can pass where the current one does not:Check the automation client
Make sure your Playwright or Puppeteer code does not override the browser: user agent, viewport, locale, timezone, or device emulation set by the framework replace parts of the profile’s fingerprint. Connect with the defaults. Use a patched build of Playwright or Puppeteer, such as Patchright or rebrowser. Do not use the framework’s default interactions for clicks, typing, and scrolling; use Human commands instead.Keep the page intact
Detection scripts can inspect changes towindow, document, navigator, and the DOM, including redefined properties and wrapped native functions. Do not use stealth plugins or other anti-detection libraries with Surfsky: their overrides can conflict with the browser’s fingerprint configuration or introduce detectable changes. Check your own init scripts for the same problems.
Check the request pattern
Reduce concurrency and repeat a single user flow. Wait for each page state before triggering the next action. Use Human commands for input and follow Human behavior for action order and timing. Compare the results after each change. Test navigation through the site’s search, menus, or internal links if opening the target URL directly fails. Where the task allows, vary the route between sessions. If the target requires many navigation steps and the site allows it, you can change an existing internal link’s destination and click it. The navigation then originates from that page. This modifies the DOM and may be detected (see Keep the page intact), so test it on the target first. If a challenge appears, confirm the selected CAPTCHA solver is enabled and observe its completion or failure events.Keep a profile that got through
On a well-protected site a browser is often let in only after a proof-of-work check, a CAPTCHA, or a few pages of ordinary browsing. A one-time profile has to earn that again on every start, and each attempt is a fresh chance to be blocked. Once a session gets through, keep it. Run such jobs on a persistent profile with cookies enabled, plus local storage if the site keeps its clearance there. Stop the session through the API so the state is saved, then start the same profile for the next run. The site sees a returning browser with valid cookies instead of a new one to challenge. Keep the proxy stable for that profile. A clearance tied to one IP is useless from another; see session control.Report the site
If the site still blocks you after these steps, tell us withPOST /site-reports or the Report a blocked site button in the dashboard. Describe the block or challenge you saw, the status code, and the proxy and profile settings you tried.
Sessions that will not stay logged in
Work through the checklist in cookies for storage options, browser context, and expired logins. Two causes come from session handling:- The profile was still running. Starting a running profile returns the existing session and ignores the settings in the new request, so a proxy, fingerprint, or storage change appears to have no effect. Check
GET /profiles/active, stop the session, then start again. - The previous session ended in a crash or infrastructure failure. An explicit stop and an inactivity stop both save the enabled storage. A crash does not, so anything done after the last saved stop is lost.
Navigation and scraping timeouts
An expired wait looks the same from your code whether the page never loaded, the state you waited for never arrived, or the wait was too short. Capture the page where it fails:- The page never loaded.
gotoraised, or the URL and content are empty. Look at the failed requests in DevTools, and check whether domain blocking removed something the page needs. A longer timeout will not bring back a resource you blocked. - The state never arrived. The HTML is there but your selector is not. Compare the captured page with the one you expect: a challenge page, a different language, or an element inside an iframe all end up here.
- The wait was too short. The content sits in the captured HTML, or appears when you repeat the run with a much longer timeout. Measure how long it really takes, then set the timeout above that.
networkidle never settles on a site with continuous background traffic, so wait for a selector that proves the content is ready instead.
A wait that outlives the inactivity timeout ends with a closed target rather than a timeout from your framework.
A failed Scraping API call returns 400 scrape_timeout and no page to inspect. Repeat it with wait_until: "domcontentloaded" and no wait_for to see what the browser actually received, then put the wait condition back. Its per-page timeout applies to each navigation or selector wait inside the 120-second budget.
The browser stopped by itself
A browser stops afterbrowser_settings.inactive_kill_timeout seconds without activity. The default is 30 seconds. Activity means CDP commands sent by your client, ChromeDriver requests, and Scraping API calls. A connection that sends nothing, an idle DevTools tab, and a screencast viewer do not count.
One long client-side wait can be a single CDP command. A waitForSelector with a 60-second timeout under the default setting can fail with Target closed because the browser stopped at 30 seconds. Raise the timeout for such waits and for manual inspection:
CDP errors and disconnections
GET /profiles/active to confirm the browser still exists. A stopped session’s connection URL will not restart it: the WebSocket opens and closes at once with the reason Profile not found. Start a session and use the returned URL.
Page limit
Target.createTarget calls, including ones still in flight. The initial tab and popups opened by the site are not counted. A slot is released when your client closes the page or the browser destroys it.
Close pages you no longer need, or reuse one. For independent parallel work, use separate browsers within your account’s concurrency limit.
Everything feels slow
Measure startup, navigation, interaction, and extraction separately. Check speed optimization for reducing commands, waits, and downloads. Increase concurrency only while it increases completed jobs per minute. If pages are slow through a Surfsky pool, check whether the request sets a location. Without targeting, peers are drawn worldwide and the exit IP can be far from the target site. Set acountry, or a pool such as europe, near it; see location targeting.
For framework-specific connection and cleanup details, use the Playwright, Puppeteer, or Selenium quickstart.
Reporting a problem
Send support:- A minimal request or script that reproduces the failure.
- The HTTP status, error response, and
x-cloud-tracing-uuidheader. - The approximate time in UTC and the API host used.
- The expected page result and what happened instead.
internal_uuid privately if support needs the session identifier. Remove API tokens, proxy passwords, cookies, provider keys, and live connection URLs before sharing logs or screenshots.