apostate: prefix and the Node package with [Apostate], and the browser prefixes its own refusals with apostate:.
When nothing here matches, run the same launch in host mode to tell whether the persona or the host and network cause the problem, and read the limitations list of --fingerprint-explain.
Installing the browser
Release manifest is unpublished
Release manifest is unpublished
github.com, or the release for this package version has no archive for this platform.Fix. Check that the host can reach github.com. apostate info lists the URLs it tried under manifest_urls_tried. On a host with no internet access, follow Offline installs.Apostate does not ship a binary for this host
Apostate does not ship a binary for this host
Apostate does not ship a binary for host darwin/x64; supported targets are linux-x64, linux-arm64, macos-arm64, windows-x64.Cause. The host is not one of the four supported platforms, for example an Intel Mac.Fix. Run on Linux x64, Linux arm64, macOS on Apple silicon or Windows x64. See Installation.SHA-256 verification failed
SHA-256 verification failed
SHA-256 mismatch for apostate-152.0.7977.83-<platform>.<ext>.Cause. The bytes downloaded are not the archive the manifest names. The download was cut short or damaged, a mirror set in APOSTATE_DOWNLOAD_BASE_URL serves other bytes, a network appliance rewrote the response, or --manifest names a different build.Fix. Run apostate install --force to download again. Unset APOSTATE_DOWNLOAD_BASE_URL to rule out the mirror. Nothing was extracted, so the cache is unchanged.Cannot read a .tar.zst archive (Linux)
Cannot read a .tar.zst archive (Linux)
this system cannot read a .tar.zst archive: install the zstd command line tool, or a tar new enough to accept --zstd.Cause. The Linux archives are zstd-compressed, and nothing on the host can read them.Fix. Install the zstd command, for example sudo apt install zstd, and run apostate install again.Cannot download binary artifact through proxy (Node)
Cannot download binary artifact through proxy (Node)
launch() was given a proxy and has no browser installed yet. It does not download the browser through the launch proxy.Fix. Run npx apostate install once without the proxy, then launch with it.A path you named has no browser
A path you named has no browser
binary_path, the Python package adds Omit binary_path to let the package find an existing install, or download and verify the release artifact. The Node package names the configured path.Cause. binary_path, executablePath or APOSTATE_BINARY points somewhere that is not the browser.Fix. Point it at the executable, a Chromium.app bundle, or the directory the archive unpacks to, such as apostate-152.0.7977.83-linux-x64/. Or unset it and let the package find or download the browser.A browser you installed by hand is not found
A browser you installed by hand is not found
apostate info shows why:no Apostate payload beside it (build/MANIFEST.lock or resources/profiles/catalogue.json), reports Chromium <version>, not 152.0.7977.83, version could not be established and not executable.Fix. Move the whole extracted directory into a well-known location, not the browser alone: build/MANIFEST.lock and resources/profiles/ must sit beside it. Or name it with APOSTATE_BINARY. Installation lists the locations.Executable doesn't exist, please run playwright install
Executable doesn't exist, please run playwright install
launch(), which looks for Playwright’s Chromium, not Apostate.Fix. Import launch from apostate or @heretic-tech/apostate. If you drive the binary yourself, pass executable_path (Node: executablePath) with the path apostate path prints. Do not run playwright install; it downloads a stock Chromium that presents your real machine.No Playwright-compatible driver is installed
No Playwright-compatible driver is installed
npm install patchright.Promise.withResolvers is not a function (Node 20)
Promise.withResolvers is not a function (Node 20)
Promise.withResolvers. The package uses it for the GeoIP lookup, Linux archive extraction, Widevine provisioning, launchProcess() and the Xvfb display, so all of these fail on Node 20.Fix. Use Node 22 or later. The Node package and the MCP server both need it.Launching
Xvfb is not installed
Xvfb is not installed
headless=False) on a Linux host with no display. The packages start a private Xvfb display for it and need the Xvfb program.Fix. Run sudo apt install xvfb, or launch headless. Linux servers has the details.Missing X server or $DISPLAY
Missing X server or $DISPLAY
apostate run or the binary itself. The package launch functions and Node’s launchProcess() start Xvfb for a headed launch. The CLI and the binary do not.Fix. Add --headless=new, or run the browser under xvfb-run. It needs the xauth package as well as xvfb. Pass --no-first-run too, or a headed first launch of a new user data directory can stop at a first-run dialog:A headed launch stops at a first-run dialog
A headed launch stops at a first-run dialog
--no-first-run. apostate run and the binary add nothing to the switches you pass. In 0.4.3, Node’s launchProcess() did not pass it either, so its DevTools port never opened.Fix. Add --no-first-run and --no-default-browser-check to the switches. The package launch functions pass both, and from 0.4.4 so does launchProcess().Running as root without --no-sandbox is not supported
Running as root without --no-sandbox is not supported
--no-sandbox by default, so this shows under Puppeteer, launchProcess(), apostate run and the binary itself, often in a container.Fix. Run as a regular user. If you must run as root, add --no-sandbox to the switches.Target page, context or browser has been closed, at launch
Target page, context or browser has been closed, at launch
apostate:. Common refusals: a core count or memory size above the host’s, a GPU renderer string not in the launch’s GPU family, a screen smaller than --window-size, a seed with spaces or over 512 bytes, and a proxy credential the browser cannot parse.Fix. Change the value the apostate: line names. Switches lists what each switch accepts. With a proxy set, the Python package cuts the message at the proxy URL, which drops the apostate: line. Run the launch once without proxy to read it.With 0.4.3, the message can include the --apostate-profile switch, which holds the proxy credential base64-encoded. Remove it before you share the message. From 0.4.4 the packages replace it with <redacted>.launch() cannot take a persistent profile
launch() cannot take a persistent profile
userDataDir in launch() and --user-data-dir in args the same way.Cause. A user data directory makes a persistent context, and launch() returns a browser.Fix. Call launch_persistent_context(DIR, ...) (Node: launchPersistentContext(DIR, options)). See Seeds and identity.Host inheritance and a persona together
Host inheritance and a persona together
apostate: --fingerprint names an off value, so no profile is composed and --fingerprint-platform cannot take effect.Cause. fingerprint="host" (or off, false, 0, disable, disabled) turns composition off, so a persona, a GPU family or a per-field switch has nothing to change.Fix. Drop one of the two: host mode for the real machine, or a seed and persona for a composed one.A switch is not one this browser reads
A switch is not one this browser reads
--fingerprint* switch in args. Chromium ignores unknown switches, so the packages refuse them, and also refuse a switch one or two letters away from a real one.Fix. Correct the spelling. Switches lists them all.--fingerprint-noise=false turns readback noise on
--fingerprint-noise=false turns readback noise on
--fingerprint-noise takes no value. The browser only checks whether it is present, so any value turns noise on, and the packages refuse values that read as off.Fix. Leave the switch out to keep noise off.Sync API inside the asyncio loop (Python)
Sync API inside the asyncio loop (Python)
launch() where an asyncio loop is already running, such as in a Jupyter notebook. In 0.4.3 a second launch() in a thread that still has a browser open fails the same way.Fix. Use launch_async(), launch_context_async() or launch_persistent_context_async() with await. From 0.4.4, browsers launched in one thread share its driver, so several can be open at once. Python has both ways.Proxies and network
net::ERR_SOCKS_CONNECTION_FAILED
net::ERR_SOCKS_CONNECTION_FAILED
SOCKS5 proxy rejected the supplied credentials.Fix. Check the host, port, username and password. Percent-encode /, % and spaces in the credential as %2F, %25 and %20. Test the proxy outside the browser:net::ERR_HTTP_RESPONSE_CODE_FAILURE behind an HTTP proxy
net::ERR_HTTP_RESPONSE_CODE_FAILURE behind an HTTP proxy
407 Proxy Authentication Required, so the credentials were rejected. This is the error a page load gets against a proxy that refuses every credential.Fix. Check the username and password, encoded as above.Browser does not support socks5 proxy authentication
Browser does not support socks5 proxy authentication
proxy option in context_options or in a script that drives the binary itself. The drivers refuse it before the browser starts.Fix. Pass the proxy through the package’s proxy option, which hands the credential to the browser and not to the driver. When you drive the binary yourself, put the credential in the switch instead of the driver’s proxy option: --proxy-server=socks5://user:pass@proxy.example:1080. See Proxies.socks5h:// does not work
socks5h:// does not work
socks5h:// is not a Chromium proxy scheme. The Node package refuses it with proxy must be a valid HTTP(S), SOCKS4, or SOCKS5 URL.Fix. Use socks5://. The browser already resolves host names on the proxy with it.--proxy-server cannot be passed in args (Node)
--proxy-server cannot be passed in args (Node)
--proxy-server itself, splitting the endpoint from the credential.Fix. Pass proxy: "socks5://user:pass@proxy.example:1080" instead.GeoIP lookup failed
GeoIP lookup failed
ip-api.com, ipinfo.io, ipwho.is and ifconfig.co over plain HTTP, through the proxy, for the exit’s country and timezone. None answered within the time limit (20 seconds), because the proxy blocks port 80, rejected the credential, or the services were unreachable. The launch goes ahead with the host’s timezone and the persona’s default language, en-US. The Node package also puts the warning in browser.apostateDiagnostics.warnings, and from 0.4.4 the Python package puts it in browser.apostate_diagnostics["warnings"]. The 0.4.3 packages print an older wording, which says the launch keeps the host’s locale. The persona uses en-US in that case.Fix. Pass locale and timezone yourself when you know the exit’s location. Raise geoip_timeout (Node: geoipTimeoutMs) for slow proxies. See Locale and timezone.The GeoIP lookup resolved no timezone, or returned no country
The GeoIP lookup resolved no timezone, or returned no country
timezone or locale yourself.Wrong values on a page
The language ignores --lang
The language ignores --lang
--lang has no effect on a persona. The persona’s language comes from --fingerprint-locale, which the packages set from the locale option or from GeoIP. Without either, it is en-US.Fix. Pass locale="de-DE" (Node: locale: "de-DE"), or --fingerprint-locale=de-DE to the binary.The timezone is the host's
The timezone is the host's
geoip=False with no timezone, or a GeoIP lookup that failed. The browser then keeps the host’s timezone.Fix. Pass timezone="Europe/Berlin" or another IANA name.The timezone reads undefined, or is not an IANA zone name
The timezone reads undefined, or is not an IANA zone name
timezone option is not an IANA zone. From 0.4.4 the packages refuse it before launch, Python with this ConfigurationError and Node with a RangeError that says the same. The 0.4.3 packages passed it to the browser, and a page’s Intl.DateTimeFormat().resolvedOptions().timeZone read undefined.Fix. Pass an IANA name such as Europe/Berlin or America/New_York.A Windows persona shows few fonts
A Windows persona shows few fonts
apostate fonts install windows. It needs git, and on Linux fc-cache from fontconfig, and it prints any core Windows family still missing. Fonts covers macOS personas and checking. Do not check with document.fonts.check(), which returns true for any family name. Measure text widths instead.The core count or memory differs from another host
The core count or memory differs from another host
--fingerprint-hardware-concurrency and --fingerprint-device-memory.A persistent profile presents a different machine
A persistent profile presents a different machine
fingerprint_platform on every launch. Compare the seed and catalogue lines of --fingerprint-explain with a launch that looked right. Seeds and identity explains each.prefers-color-scheme is always light
prefers-color-scheme is always light
color_scheme="null" in Python, or call await page.emulateMedia({ colorScheme: null }) on each page in Node. Known gaps has the details.The screen is 800x600 with availHeight equal to height
The screen is 800x600 with availHeight equal to height
--fingerprint=host and no display, the page reads Chrome’s own headless screen.Fix. Use a seed, or launch headed.The screen, window and viewport are all 1280x720 at pixel ratio 1
The screen, window and viewport are all 1280x720 at pixel ratio 1
viewport=None as the 1280x720 default.Fix. Pass no_viewport=True in Python or viewport: null in Node. See Screen and window.