Skip to main content
The Python package (apostate on PyPI) finds or downloads the browser, looks up the proxy’s exit, and starts the browser through Patchright, a Playwright build. It returns Playwright objects, so the rest of your script is ordinary Playwright code. Installation covers pip install apostate and the browser download.

Launch a browser

fingerprint is the seed. The same seed and persona give the same machine on every launch. fingerprint_platform is the persona, the operating system the browser presents. Personas and Seeds and identity explain both. launch() returns Playwright’s Browser. The browser runs on a temporary normal profile, which is deleted when the browser closes. new_page() opens pages in that profile. The first call returns the blank tab the browser started with.
new_context() opens an off-the-record context, as it does in Playwright, and sites can tell an off-the-record context from a normal profile. Open pages with new_page().
new_page() takes no options, because every page shares the one profile. Pass page options such as viewport or color_scheme to launch() instead.

Entry points

Each has an async version: launch_async(), launch_context_async() and launch_persistent_context_async(). launch_context() takes the same options as launch(), plus context_options, which apply to the context when it starts. Closing the context closes the browser.
launch_persistent_context() keeps a profile in a directory. The first launch stores a seed in DIR/apostate/identity, and every later launch with that directory presents the same machine. launch() refuses a user data directory.
Two runs of this script print the same values. On the host used here:

Async API

The async functions take the same options as the sync ones.

Several browsers at once

Give each browser its own seed or its own user data directory. Two browsers cannot open one user data directory at the same time, and the second launch fails with a LaunchError that names a ProcessSingleton. From 0.4.4, the sync API can keep several browsers open in one thread. They share the thread’s driver, and the last close() stops it.
On a Mac with 14 cores:
In 0.4.3, a second launch() while the first browser is still open fails with It looks like you are using Playwright Sync API inside the asyncio loop. On 0.4.3, use the async API, which runs several browsers from one event loop. Many sessions runs them with asyncio.gather() and a limit on how many are open.

Options

Proxies, Locale and timezone, Custom profiles and Linux servers cover the options in use. Python API lists every function and option, and Switches lists what args accepts.

Playwright options

Any other keyword goes to Playwright’s launch_persistent_context(), which takes Playwright’s launch options and its context options together.
The package sets some of these itself:
  • executable_path, headless, args and user_data_dir come from the package. Use binary_path, headless and args instead.
  • env goes over the browser’s environment, which the package gives LANGUAGE, LC_ALL, LC_MESSAGES, LANG and TZ (Locale and timezone). Your entries win.
  • ignore_default_args gets --disable-component-update added, so the driver does not pass that switch (Widevine).
  • viewport is off unless you pass one, so the page gets the persona’s real window size. A viewport of your own changes the screen a page sees (Screen and window).
  • From 0.4.4, color_scheme is "null" unless you pass one, so a page reads the persona’s own light or dark theme. The 0.4.3 package left the driver’s light emulation on (Known gaps).
  • proxy comes from the package’s proxy option.

Warnings

From 0.4.4, the object launch() or launch_persistent_context() returns carries apostate_diagnostics, a dict of what the launch resolved. A context from launch_context() carries its browser as context.apostate_browser, which has it.
proxy.example does not resolve, so the lookup fails:
The package also prints each warning to stderr as one line that starts with apostate: . The 0.4.3 package has no apostate_diagnostics, and its GeoIP warning is worded differently. To read warnings in code on 0.4.3, capture stderr during the launch:
browser.apostate_driver_name names the driver that started the browser. To see the whole machine a launch presents, run --fingerprint-explain (Verify):

Drivers

Patchright is installed with the package and is the default driver. To use Playwright instead, install it and pass driver="playwright":
Do not run playwright install. Apostate brings its own browser. driver_info() reports what is installed and which driver a launch would use:
Detection has what a page can see of each driver.

Host mode

fingerprint="host" presents the host’s own values and composes nothing. "off", "false", "0", "disable" and "disabled" mean the same. Use it to tell whether a problem comes from the persona or from the host and network.
That output is from a Mac. Host mode refuses fingerprint_platform with a ProfileError, and the package sets no locale variables. Headless host mode reports an 800x600 screen (Screen and window).

Close the browser

browser.close() closes the browser, deletes its temporary profile, and stops any Xvfb display the package started. It stops the driver too, unless another browser in the same thread still uses it. launch() and launch_persistent_context() also work as context managers, as the examples above show. Closing a context from launch_context() closes its browser. Close every browser you launch. The sync driver keeps an event loop in the thread until its last browser closes.

Errors

Every package error is a subclass of ApostateError.
Errors lists the common messages and what to do about each.