Free tools Windows power users keep installed
One-click scans. No signup required.
A cloud browser is another computer. When a page downloads a file there, the bytes normally remain in that browser session or its container. They do not appear automatically on the machine running your automation code. To retrieve the file, start listening before the click, wait for download completion, and explicitly copy the bytes to the controlling process. Playwright can save a completed download directly with Download.saveAs(); Browserless offers both a CDP event carrying base64 data and a one-shot REST /download workflow.
The correct mental model: two machines, two filesystems
In a hosted browser setup, your script and the browser may run in different machines, containers, or processes. A browser download is first created in the remote browser context. Your local path only receives a copy when the automation framework or provider transfers it.
Therefore, saveAs('/tmp/report.pdf') means “write on the machine running this Playwright process,” not “write inside the browser container.” The same distinction applies to CI workers, serverless functions, and development laptops connecting to a remote endpoint.
- Keep the browser session alive until the download has completed and the transfer has finished.
- Register the download listener before clicking the link or button. A listener installed afterward can miss a fast download.
- Persist files you need before closing the browser context. Playwright’s downloaded files are temporary and are deleted when the context that produced them closes.
- Handle filename, MIME type, size, and errors explicitly rather than assuming a successful HTTP response means a file was saved.
Playwright: save a remote download to the controlling machine
Use this method when your remote connection supports Playwright’s download API. The essential sequence is: create the waiter, trigger the download, await the Download object, then call saveAs().
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
#1 Best Overall
- Easily store and access 2TB to content on the go with the Seagate Portable Drive, a USB external hard drive
- Designed to work with Windows or Mac computers, this external hard drive makes backup a snap just drag and drop
- To get set up, connect the portable hard drive to a computer for automatic recognition no software required
- This USB drive provides plug and play simplicity with the included 18 inch USB 3.0 cable
- The available storage capacity may vary.
JavaScript example
import { chromium } from 'playwright';
const browser = await chromium.connectOverCDP(process.env.BROWSER_CDP_URL);
const context = browser.contexts()[0];
const page = await context.newPage();
await page.goto('https://example.com/reports');
// Install the waiter before the click that starts the download.
const downloadPromise = page.waitForEvent('download');
await page.getByRole('link', { name: 'Download report' }).click();
const download = await downloadPromise;
const suggested = download.suggestedFilename();
await download.saveAs(`/var/tmp/${suggested}`);
const failure = await download.failure();
if (failure) throw new Error(`Download failed: ${failure}`);
await context.close();
await browser.close();
The destination path belongs to the process running this code. In a CI job, that may be the CI worker; in a service, it may be an ephemeral container. Upload or move the saved file to durable storage if it must survive that process.
Preserving or replacing the filename
suggestedFilename() returns the browser-proposed name. It is useful when the server supplies a meaningful name, but treat it as untrusted input: remove path separators, control characters, and unexpected extensions before using it in a shared directory. You can instead choose a fixed name such as /var/tmp/export-2026-09-29.csv.
Waiting for the right event
Some controls open a menu, navigate, or start a client-side request before the eventual download. Put the waiter around the action that actually initiates the browser download. If a click both navigates and downloads, Playwright’s download event is still the completion signal; do not close the page after the click alone.
Temporary-file lifecycle
Call saveAs() before closing the context. A context shutdown removes the temporary download even if the browser UI appeared to finish successfully. If your process can be interrupted, save promptly and use an atomic rename after the write completes.
Browserless CDP: receive file bytes as an event
Browserless provides a vendor-specific CDP flow for applications that want the payload in their own code. Download transfer is disabled by default in the documented flow because file bytes count against data transfer.
Rank #2
- Easily store and access 5TB of content on the go with the Seagate portable drive, a USB external hard Drive
- Designed to work with Windows or Mac computers, this external hard drive makes backup a snap just drag and drop
- To get set up, connect the portable hard drive to a computer for automatic recognition software required
- This USB drive provides plug and play simplicity with the included 18 inch USB 3.0 cable
- The available storage capacity may vary.
- Enable downloads for the session with the Browserless method
Browserless.setDownloadEnabled. - Register a
Browserless.fileDownloadedlistener before clicking the download control. - Trigger the download and wait for the event.
- Read its
filename,mimeType,size, and base64-encodeddata. - Decode the base64 string and write the resulting bytes in the client process.
Illustrative Node.js CDP handling
import fs from 'node:fs/promises';
import puppeteer from 'puppeteer-core';
const browser = await puppeteer.connect({ browserWSEndpoint: process.env.BROWSERLESS_WS });
const page = await browser.newPage();
const client = await page.createCDPSession();
await client.send('Browserless.setDownloadEnabled', { enabled: true });
const fileDownloaded = new Promise((resolve, reject) => {
const timer = setTimeout(() => reject(new Error('Download timed out')), 90000);
client.once('Browserless.fileDownloaded', event => {
clearTimeout(timer);
resolve(event);
});
});
await page.goto('https://example.com/reports');
await page.click('text=Download report');
const file = await fileDownloaded;
const bytes = Buffer.from(file.data, 'base64');
await fs.writeFile(`/var/tmp/${file.filename}`, bytes);
console.log({ name: file.filename, type: file.mimeType, size: file.size });
await browser.close();
The method names and event shape are Browserless-specific, not portable Playwright APIs. Validate the event’s declared size against the decoded byte length, reject unsafe filenames, and impose your own maximum before allocating memory for large files. The documented 50 MB combined decoded limit applies to a Browserless upload call, not to downloads; do not use it as a download ceiling.
Browserless REST /download: one request, one returned file
Choose the REST endpoint when custom Puppeteer code can express the job and your application prefers an HTTP response containing the downloaded file. Browserless describes this as a request that launches a browser, performs one task, and closes the session. The response includes content-type and content-disposition headers suitable for saving the result.
Your request body supplies the Puppeteer code that navigates to the page and clicks the download control. The caller then treats the HTTP response as file data, checks the status and headers, and streams it to durable storage. Because the endpoint owns the browser lifecycle, it is convenient for isolated jobs but less suitable when several downloads share a long-lived session.
Recommended Free Tools
Choosing a transfer path
| Path | Where bytes arrive | Transfer switch | Best fit |
|---|---|---|---|
| Playwright download event | File written by Playwright to the controlling process via saveAs() |
Provided by the framework when supported | Portable Playwright automation |
| Browserless CDP event | Your event handler decodes base64 and writes the file | Enable Browserless.setDownloadEnabled |
Browserless sessions needing metadata and event-driven handling |
Browserless REST /download |
HTTP response stream | Built into the endpoint workflow | One task per request with custom Puppeteer code |
Playwright’s API is the least provider-specific. Browserless’s event and REST endpoint require Browserless and may change with that service’s API. In every case, completion must be awaited before session teardown, and your application—not the remote browser—decides the final durable path.
Reliability and security checklist
Before triggering the download
- Authenticate in the remote context and confirm the account has permission to fetch the file.
- Install the event waiter before the click.
- Set a realistic timeout for page actions and transfer completion.
- Choose a writable destination on the controlling machine and ensure sufficient disk space.
After completion
- Check framework failure status or HTTP status before treating the file as valid.
- Verify expected MIME type, filename extension, and—when known—size or checksum.
- Sanitize filenames and prevent
../traversal. - Move the completed temporary file atomically into its final location.
- Delete sensitive files according to your retention policy and protect logs from leaking credentials or personal data.
Performance considerations
Event-based transfer can hold the complete base64 payload in memory, which adds roughly one-third overhead before decoding. Stream an HTTP response where possible, or enforce a size limit and use temporary disk space for large artifacts. A one-shot REST request avoids managing a persistent session but pays the cost of launching a browser for each task. A long-lived Playwright session can amortize startup time across several downloads, provided you isolate cookies and permissions between jobs.
Rank #3
- Easily store and access 1TB to content on the go with the Seagate Portable Drive, a USB external hard drive.Specific uses: Personal
- Designed to work with Windows or Mac computers, this external hard drive makes backup a snap just drag and drop. Reformatting may be required for Mac
- To get set up, connect the portable hard drive to a computer for automatic recognition no software required
- This USB drive provides plug and play simplicity with the included 18 inch USB 3.0 cable
- The available storage capacity may vary.
Troubleshooting common failures
No download event is received
The listener was probably registered after the click, the control did not initiate a browser download, or the page opened a new tab. Create the waiter first, inspect whether the click caused navigation or a popup, and target the final control rather than a wrapper element.
The file exists remotely but not locally
The remote filesystem is not shared with your script. Use Playwright’s saveAs(), decode the Browserless event, or save the REST response in the caller. Do not search only the browser container for a path created by local code.
The saved file is empty or HTML
The server may have returned a login page, an access-denied response, or an application error instead of the expected artifact. Check authentication, response status, MIME type, and a small signature check (for example, PDF files normally begin with %PDF-) before handing the file to downstream processing.
The file disappears after success
Playwright’s temporary download was cleaned up when its context closed. Call saveAs() before shutdown and store the result outside the temporary directory.
Browserless reports excessive transfer or memory use
CDP events transfer file bytes to your client and are disabled by default for that reason. Enable them only for sessions that need them, reject unexpectedly large payloads, and prefer the REST response when streaming is more appropriate.
Rank #4
- Easily store and access 4TB of content on the go with the Seagate Portable Drive, a USB external hard drive.Specific uses: Personal
- Designed to work with Windows or Mac computers, this external hard drive makes backup a snap just drag and drop
- To get set up, connect the portable hard drive to a computer for automatic recognition no software required
- This USB drive provides plug and play simplicity with the included 18 inch USB 3.0 cable
- The available storage capacity may vary.
The REST request times out
Increase the client timeout within your service’s limits, wait for the page’s download-triggering condition, and ensure the custom Puppeteer code does not close the session before Chrome emits the completed download. Retry only when the operation is safe to repeat.
Or skip the browser setup
If your actual goal is a clean image or PDF of a web page—not an arbitrary file downloaded by a logged-in workflow—ScreenshotNeo provides a website screenshot API. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result. Its MCP server offers take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
One call returns the image or PDF bytes:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for output formats and options. The service includes full-page captures with lazy images loaded, CSS-selector element shots, dark mode, device presets and custom viewports, retina scale, PDF paper settings and page ranges, custom CSS and JavaScript, click and wait actions, hidden selectors, request and resource blocking, headers, cookies, user agent, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL-based caching, signed links, async jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API, and an OpenAPI specification. Parameter names used by other screenshot APIs also work for easier migration.
The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots; every feature is on every plan. Create a free ScreenshotNeo account to try it.
Frequently asked questions
Does downloading from a cloud browser require shared storage?
No. Shared storage is optional. The automation client can receive the completed bytes and write them to its own filesystem or to an object-storage service.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Can I close the page immediately after clicking?
Not safely. Keep the relevant page, context, or provider session alive until the download completion event or HTTP response has been fully handled.
Best Value
- Plug-and-play expandability
- SuperSpeed USB 3.2 Gen 1 (5Gbps)
Which approach should I use for repeated downloads?
Use a long-lived Playwright connection when framework portability and session reuse matter. Use Browserless’s REST endpoint for independent jobs where a response stream and automatic session teardown simplify operations.
Frequently Asked Questions
Does downloading from a cloud browser require shared storage?
No. The client can receive the completed bytes and write them locally or to object storage; shared storage is optional.
Can I close the page immediately after clicking?
No. Keep the page, context, or provider session alive until completion has been received and persisted.
Which approach suits repeated downloads?
A long-lived Playwright connection favors session reuse and portability; Browserless REST is convenient for independent one-task requests.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




