Skip to main content
You keep records of web pages for research or compliance, and each record has to show the page as a visitor saw it and say how and when it was made. This walkthrough captures a page into a folder with a full-page screenshot, a PDF, the rendered HTML, a HAR file of the network traffic and a manifest with the SHA-256 of each file.

What Apostate changes

Some sites answer automated or headless browsers with a challenge page or less content. Apostate presents a desktop machine without the automation traces those sites check for (Detection), so the capture shows the page a visitor on that machine gets. A persona is the platform the browser presents, and a seed selects the machine. The manifest records both, and a later capture with the same seed uses the same machine.

Set up

apostate fonts install windows is for Linux and macOS hosts (Fonts). archive.py captures each URL you pass, and https://example.com when you pass none. Each capture goes into out/<host>-<UTC time>/.

The script

record_har_path is a Playwright option. launch() passes Playwright’s launch and context options through (Python). Playwright writes the HAR file when the browser closes, so the script hashes the files after the with block.

Run it

manifest.json in the same folder:
To check a file later, hash it again and compare with the manifest. On macOS:
On Linux, sha256sum prints the same.

What each file holds

Points for this job

  • Seed and persona. The manifest records both, with the Apostate and browser versions. A later capture with the same seed, persona and version uses the same machine. A release that changes the catalogue tables can change it (Seeds and identity).
  • Region. With APOSTATE_PROXY set, every page loads through that proxy, and the package sets the locale and timezone from the proxy’s exit. Without a proxy, --locale and --timezone set them. The manifest records the language and timezone the page read. Proxies covers proxy URLs.
  • Integrity. Anyone who can edit the folder can edit the manifest too. To show later that a record is unchanged, sign the manifest or store the folder where it cannot be changed.
  • Many pages. To archive many pages of one site, follow its terms and robots.txt and space the page loads. Price monitoring shows both.
  • Waiting. With wait_until="networkidle", page.goto() returns after 500 ms with no network connections. Content that loads on scroll or on a timer appears only if the script scrolls or waits for it before the screenshot.
  • Theme. A persona draws a light or dark theme. From 0.4.4 the page reads that theme through prefers-color-scheme. With the 0.4.3 package the page reads light unless you pass color_scheme="null" (Known gaps). To capture every page in one theme, pass color_scheme="light" or color_scheme="dark" to launch().
  • Headless. page.pdf() works only headless, the default.