Skip to main content

What is P2P Download?

P2P downloads let you receive a real-time notification the moment a file is downloaded in your browser session, then fetch the file directly from the active session — no polling, no waiting for Anchor to process the file, no storage APIs required.

How It Works

Traditional downloads:
Browser downloads file → Anchor stores the file → You poll GET /downloads → Fetch from Anchor storage
P2P downloads:
Browser downloads file → Anchor.downloadReady CDP event fires → You fetch directly from the browser
When a file is downloaded, the browser emits a custom CDP event (Anchor.downloadReady) over your existing WebSocket connection. The event includes a pre-built fetch URL that streams the file bytes directly from the browser’s disk.

Implementation

1

Connect to the session and listen for the CDP event

Connect Playwright over CDP as usual, then open a CDPSession on the page to listen for the Anchor.downloadReady event.
import { chromium } from "playwright";
import AnchorBrowser from "anchorbrowser";
import fs from "fs";

const { ANCHOR_API_KEY } = process.env;
const client = new AnchorBrowser({ apiKey: ANCHOR_API_KEY });

const session = await client.sessions.create();
const { cdp_url, id: sessionId } = session.data;

const browser = await chromium.connectOverCDP(cdp_url);
const page = browser.contexts()[0].pages()[0];

const cdpSession = await page.context().newCDPSession(page);

const downloadReady = new Promise((resolve) => {
  cdpSession.on("Anchor.downloadReady", (params) => resolve(params));
});
2

Trigger the download

Use Playwright as normal to navigate and click the download link.
await page.goto("https://example.com/reports");
await page.click("#download-report");
3

Receive the event and fetch the file

Wait for the Anchor.downloadReady event, then use the p2pDownloadUrl from the event params to fetch the file.
// Wait for the download event
const event = await downloadReady;

console.log(`Download ready: ${event.suggestedFilename} (${event.size} bytes)`);

// Fetch the file directly from the session
const response = await fetch(
  `https://api.anchorbrowser.io${event.p2pDownloadUrl}`,
  { headers: { "anchor-api-key": ANCHOR_API_KEY } }
);

fs.writeFileSync(
  event.suggestedFilename,
  Buffer.from(await response.arrayBuffer())
);

console.log(`Saved ${event.suggestedFilename}`);
await browser.close();

The Anchor.downloadReady Event

The event is emitted on the CDP WebSocket connection as soon as the file lands on disk.
{
  "method": "Anchor.downloadReady",
  "params": {
    "localDownloadId": "4e901615-5f83-4773-a1af-773e15a19be8",
    "suggestedFilename": "report.pdf",
    "url": "https://example.com/report.pdf",
    "originUrl": "https://example.com/reports",
    "size": 1048576,
    "duration": 2300,
    "p2pDownloadUrl": "/v1/sessions/{sessionId}/downloads/{localDownloadId}/p2p"
  }
}
FieldDescription
localDownloadIdUnique ID for this download, valid for the lifetime of the session
suggestedFilenameThe filename as suggested by the browser
urlThe URL the file was downloaded from
originUrlThe page URL where the download was triggered
sizeFile size in bytes
durationTime to complete the download in milliseconds
p2pDownloadUrlRelative URL to fetch the file — prepend your API base URL

Fetch Endpoint

GET /v1/sessions/:session_id/downloads/:local_download_id/p2p
This endpoint streams the file directly from the active session. It is only available while the session is active. Once the session ends, use the standard session downloads API to retrieve files from Anchor storage.
StatusMeaning
200File streamed successfully
404local_download_id not found (may have expired with the session)
410Session is no longer active — use the standard /downloads/:id/fetch instead

Limitations

  • The P2P fetch URL is only valid while the session is running. After the session ends, the file is no longer accessible via this endpoint.
  • Files are still stored by Anchor in the background as a fallback. Once the session completes, they are accessible via the standard list session downloads API.
  • Blob and data URL downloads (files generated client-side in JavaScript) are supported.