Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Antihost offers VPS plans with one-click Docker, NVMe storage and a 14-day free trial.
Run the scraper as a small, restartable service: pin a Node version of 22.12 or newer, lock Puppeteer in package-lock.json, use Puppeteer’s Chrome-ready image or a Debian/Ubuntu-based image, start the container with an init process and the sandbox capability, allocate enough /dev/shm, and schedule jobs on the VPS. The example below adds explicit waits, bounded retries, structured output, diagnostics, graceful shutdown, health reporting, log rotation, and conservative concurrency before you collect production data.
What you are building
The application has four layers:
- Scraper code: Node.js launches Chromium through Puppeteer, navigates to an allowed URL, waits for the page state you actually need, validates the result, and writes structured records.
- Container: Docker packages the code, Node runtime, browser, fonts, and operating-system dependencies so the VPS does not need a desktop installation.
- VPS service: A Linux host supplies persistent storage, a scheduler, firewall rules, restart handling, and log retention.
- Collection policy: You define permitted domains, fields, request rate, retention period, and what happens after repeated failures before enabling unattended runs.
This design is appropriate for periodic collection and moderate parallelism. It is not permission to defeat authentication, paywalls, robots directives, rate limits, bot controls, or a site’s terms. Obtain the site owner’s permission where required, minimize personal data, and review copyright and privacy obligations before storing results.
Free tools Windows power users keep installed
One-click scans. No signup required.
Prerequisites and sizing
| Requirement | What to use | Why it matters |
|---|---|---|
| Node.js | 22.12 or newer | Current Puppeteer system requirements specify this minimum. |
| Operating system | Linux VPS running a supported Debian or Ubuntu distribution, on x64 or arm64 | Chrome for Testing publishes binaries for these architectures, but required distribution packages still have to be present. |
| Docker | A recent Docker Engine and Compose plugin, if you use Compose | The browser and its dependencies run inside the container rather than on the host. |
| Memory | Begin with at least 2 GB RAM for a single modest worker; add capacity for each concurrent browser | Chromium processes, page content, Node, and the kernel’s shared-memory mount all consume memory. Measure your workload instead of assuming a fixed limit. |
| Storage | Persistent volume for results and a bounded area for logs and diagnostic screenshots | Browser profiles and failure artifacts can fill a small disk if they are never removed. |
| Network | Outbound HTTPS and DNS; no public Docker socket | The scraper must reach targets, while the Docker control API must remain private. |
Check the VPS architecture with uname -m, verify Docker can start a simple container, and confirm that your target’s DNS and TLS chain work from the VPS. Keep Node and Puppeteer versions aligned: commit the lockfile, rebuild after deliberate upgrades, and test navigation and extraction together rather than upgrading either component independently.
Create a small, reliable scraper
1. Initialize the project and lock dependencies
mkdir puppeteer-scraper
cd puppeteer-scraper
npm init -y
npm install --save-exact puppeteer
npm pkg set scripts.start="node src/scraper.js"
mkdir -p src data logs
--save-exact records the selected Puppeteer release rather than a floating range. Commit both package.json and package-lock.json. Confirm the installed package supports Node 22.12 or newer before building the image. Keep a short change log containing the Node version, Puppeteer version, browser revision, and the date each was tested.
#1 Best Overall
- Powerful Turbo Fan:CAGIWIRU Electric Air Duster have reached speed up to 130000RPM,Can efficient remove dust and debris.With LED light and Three Adjustable Speed to meet with different cleaning tasks.
- With Attached USB C Fasting Charging cable.Charing 3 hours,Enjoy up to 240 minutes of use on the lowest setting, For third speed can use for 25mins.with four charging options to meet with your needs.
- Wide Application: attached 5 different nozzles,making it suitable for a variety of scenes, such as car,pet, pc, keyboards, and other electronic devices. It also serves for office and home clean duster.
- Handy Design & Portable:Cordless air duster electric nozzle is Light weight and small size, design and comfortable to hold and space saving, convenient to carry around. You can put it in your room or inside the car without taking up space.
- Economical &Reusable: Built durable materials with a long-lasting battery,our CAGIWIRU air duster it's a sustainable alternative to disposable air cans.
2. Implement navigation, extraction, retries, and cleanup
The following example collects article cards from an illustrative, permitted endpoint. Replace the URL and selectors with values documented for your target; do not infer that the selectors or fields apply to another site.
const puppeteer = require('puppeteer');
const fs = require('node:fs/promises');
const TARGET_URL = process.env.TARGET_URL || 'https://example.org/articles';
const OUTPUT_FILE = process.env.OUTPUT_FILE || '/app/data/articles.jsonl';
const MAX_ATTEMPTS = Number(process.env.MAX_ATTEMPTS || 3);
const NAVIGATION_TIMEOUT = Number(process.env.NAVIGATION_TIMEOUT || 30000);
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
async function scrapeOnce(browser) {
const page = await browser.newPage();
page.setDefaultNavigationTimeout(NAVIGATION_TIMEOUT);
page.setDefaultTimeout(NAVIGATION_TIMEOUT);
await page.setRequestInterception(true);
page.on('request', request => {
const type = request.resourceType();
if (['image', 'media', 'font'].includes(type)) request.abort();
else request.continue();
});
try {
await page.goto(TARGET_URL, { waitUntil: 'domcontentloaded' });
await page.waitForSelector('article.card', { visible: true });
await page.waitForFunction(() => document.querySelectorAll('article.card').length > 0);
const rows = await page.$$eval('article.card', cards => cards.map(card => ({
title: card.querySelector('h2')?.textContent?.trim() || null,
url: card.querySelector('a')?.href || null,
summary: card.querySelector('.summary')?.textContent?.trim() || null
})));
if (!rows.length || rows.some(row => !row.title || !row.url)) {
throw new Error('Validation failed: expected complete article records');
}
return rows;
} finally {
await page.close();
}
}
async function scrapeWithRetry(browser) {
let lastError;
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt += 1) {
try {
return await scrapeOnce(browser);
} catch (error) {
lastError = error;
console.error(JSON.stringify({ event: 'attempt_failed', attempt, message: error.message }));
if (attempt < MAX_ATTEMPTS) await sleep(1000 * 2 ** (attempt - 1));
}
}
throw lastError;
}
async function main() {
let browser;
try {
browser = await puppeteer.launch({
headless: true,
args: []
});
const rows = await scrapeWithRetry(browser);
await fs.mkdir(new URL('.', `file://${OUTPUT_FILE}`).pathname, { recursive: true }).catch(() => {});
const payload = rows.map(row => JSON.stringify({
collectedAt: new Date().toISOString(),
source: TARGET_URL,
...row
})).join('n') + 'n';
await fs.appendFile(OUTPUT_FILE, payload, 'utf8');
console.log(JSON.stringify({ event: 'scrape_succeeded', count: rows.length }));
} finally {
if (browser) await browser.close().catch(error => {
console.error(JSON.stringify({ event: 'browser_close_failed', message: error.message }));
});
}
}
main().catch(error => {
console.error(JSON.stringify({ event: 'scrape_failed', message: error.message, stack: error.stack }));
process.exitCode = 1;
});
The selectors are intentionally explicit. A successful HTTP response does not prove that the application rendered the data, so wait for a selector or a page condition that represents readiness. Validate required fields and record a failure when the page shape changes; silently writing empty objects is harder to detect than a failed job.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC 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 & 11Use one page per unit of work and close it in a finally block. Close the browser during normal completion and shutdown so Chrome child processes do not accumulate. The request-interception example saves bandwidth, but disable it when a target needs images, fonts, or media to render the data you collect.
3. Add a health signal and bounded work
A scheduler needs to distinguish “the process exists” from “the last collection succeeded.” Write a heartbeat file or a small JSON status record only after validation succeeds. Include the timestamp, target, row count, duration, and error message for the last failed attempt. A watchdog can alert when the timestamp is older than the expected schedule.
Do not launch an unbounded number of pages with Promise.all. Start with one browser and a small page limit, then measure CPU, RAM, file descriptors, network latency, target responses, and /dev/shm usage. A queue makes back-pressure visible: jobs wait instead of causing every navigation to compete for memory.
Rank #2
- Screen Cleaner is Your Screen’s New Bestfriend! - EVEO is proud to present a screen cleaner that’s perfectly suited for your TV. Meet your new screen cleaner, computer screen cleaner, laptop cleaner, iPad cleaner, Macbook,tv cleaner or any other electronic device. Our screen cleaner spray and wipe along with the included plush microfiber cloth, easily removes dust, fingerprints & other smudges on the screen’s surface. Clean effectively for a streak-free screen
- Gentle on your Screens - Our screen cleaner spray and wipes is compatible to be used even for the most sensitive LCD, LED, CRT, and OLED screens in proper use. Be at ease knowing that this product is compatible with all the major brands: LG, SONY, Samsung, Sharp, iPad, iPhone, Android screens, Kindle, PC monitors - we’ve got you covered! Can be used as LCD screen cleaner, tv cleaner, smart tv screen cleaner, and more
- Premium Super Soft Plush Microfiber Cloth - Included in this efficient screen cleaning kit. This screen cleaner spray and wipe has our signature plush microfiber cloth specially designed to comply with screens and monitors and leave them streak-free. Has been shown to effectively absorbs stubborn stains, zero streaks, and no fiber shedding. Always use this together with our screen cleaner for the best results
- Easy-to-Use Screen Cleaner Kit + microfiber cleaning cloth - The EVEO Screen Cleaning Kit will easily be your new favorite tool when it comes to taking care of the things you love most, quick and easy solution for a streak-free screen. Simply screw on the sprayer gun on the screen cleaner bottle. Spray the cleaning liquid onto the microfiber cloth, then wipe the screen until desired cleanliness & shine is achieved.
- Quality Screen Care Kit Worth Purchasing - Enjoy a convenient Screen Cleaner anytime, anywhere you need it. Your satisfaction is our top priority. We stand behind the quality of our products and that’s why, you shouldn’t be worrying at all. We manufacture the Best Screen Cleaner. and can be used for laptop cleaning kit, laptop screen cleaner, tv screen cleaner for smart tv. MacBook screen cleaner, monitor cleaner or screen cleaner spray for electronic devices with microfiber cleaning cloth
Choose and build the Docker image
Official Puppeteer image
Puppeteer publishes an image containing Chrome for Testing, its required dependencies, and a pre-installed Puppeteer version. The documented run pattern is:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
docker run -i --init --cap-add=SYS_ADMIN --rm ghcr.io/puppeteer/puppeteer:latest
The image is designed for Chrome’s sandbox mode, so it requires the SYS_ADMIN capability. The --init flag supplies an init process that reaps orphaned children; this is important because Chrome creates several subprocesses. In production, use a tested image tag or immutable digest rather than rebuilding unexpectedly from a mutable latest tag, and keep the application’s lockfile compatible with the browser bundled in that image.
To run the sample application, add the source and data directories to an image derived from the official image. The exact base tag should be the one you tested and approved:
FROM ghcr.io/puppeteer/puppeteer:latest
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY src ./src
RUN mkdir -p /app/data /app/logs
CMD ["node", "src/scraper.js"]
Build and test it locally:
docker build -t puppeteer-scraper:test .
docker run --rm -i --init --cap-add=SYS_ADMIN --shm-size=2g
-e TARGET_URL=https://example.org/articles
-v "$PWD/data:/app/data"
puppeteer-scraper:test
Do not bake credentials into the image or copy local browser profiles into it. Pass configuration at runtime and keep the image reproducible.
Custom Debian or Ubuntu Dockerfile
A custom image is useful when you need a smaller attack surface, additional system packages, or a different process layout. Start from a Debian- or Ubuntu-based Node 22 image, install the distribution packages listed in Puppeteer’s current system requirements, run npm ci, and install or download the matching Chrome for Testing revision. Verify both x64 and arm64 behavior if you publish one image for multiple VPS architectures.
Rank #3
- 【Large size】:Measuring 800 x 300 mm/ 31. 5×12 inches, which is wider and taller than others. Large mouse pad can perfectly fit your keyboard and mouse of any size, and there is also ample space for peripherals such as phones, tablets, etc.
- 【LED backlight mouse pad】:Blade Hawks RGB mouse pad provides 7 static modes and 7 dynamic modes will give you the options you are looking for. Power-off memory function remembers the last lighting mode you selected. The super glow fiber Chroma will give you a colorful gaming setup that you want.
- 【Anti-slip rubber base】:Made from Natural rubber, this gaming mousepad will firmly grip your desktop, allowing you to enjoy the ultimate precision in the games you are most passionate about. It also comes with a texture that enhances this ability even further.
- 【Smooth and waterproof surface】: Micro-textured cloth surface, for extremely precise mouse control and a smooth movement. When liquid splashes on the gaming mouse pad, it forms water droplets and slides down. Will not delay your work or gameplay.
- 【Plug and play】: This mouse and keyboard pad is powered by USB, plug and play, no driver required. One button control light modes. Press one time to change the lighting mode, press twice to change the brightness, press and hold about 3 seconds turn ON/OFF.
Custom images transfer responsibility for browser updates, fonts, shared libraries, sandbox behavior, and CVE response to you. Build in CI, run a smoke test that launches a page, and record the exact image digest used on the VPS. Do not “fix” sandbox failures by adding --no-sandbox unless you have assessed the security consequences; preserving the sandbox is the safer default.
Run Chrome reliably inside a container
Shared memory
Docker’s default /dev/shm is 64 MB. Browserless documents that this limit can make Chrome crash under load and recommends a 2 GB shared-memory setting in Compose or with --shm-size=2g. Treat 2 GB as a starting configuration, not a guarantee: a page with large canvases, PDFs, or several concurrent tabs may need more, while a single lightweight page may need less.
docker run --rm -i --init --cap-add=SYS_ADMIN --shm-size=2g puppeteer-scraper:test
When crashes persist, inspect container memory and /dev/shm usage, reduce concurrency, close pages promptly, and capture the failing URL and browser log. Increasing shared memory cannot repair a memory leak or an exhausted VPS.
Sandbox, init, and writable paths
- Use
--cap-add=SYS_ADMINwith the official image as documented. - Always use
--initor an equivalent init entrypoint to reap Chrome’s child processes. - Provide writable temporary and profile locations. A read-only root filesystem is possible, but mount writable paths for
/tmp, Chromium’s profile, and your output volume. - Run as a non-root user where your chosen image supports it, and grant only the filesystem and network access the job needs.
- Keep the Docker socket off the public network. Anyone who can control it can usually control the host.
Diagnose common launch failures
| Symptom | Likely cause | Action |
|---|---|---|
| Chrome exits immediately with a sandbox error | Missing capability or incompatible user configuration | Use the official image’s --cap-add=SYS_ADMIN, preserve sandbox mode, and inspect the container’s stderr. |
| “Browser disconnected” or random tab crashes under load | 64 MB shared memory, RAM pressure, or too many pages | Set --shm-size=2g, lower concurrency, and monitor host memory and /dev/shm. |
| Zombie Chrome processes remain | No init process or missing cleanup path | Run with --init, close pages in finally, and close the browser on shutdown. |
| Profile or temporary-file errors | Read-only filesystem or unwritable directory | Mount writable /tmp and profile/output directories with appropriate ownership. |
| Works locally but not on the VPS | Architecture, missing distribution package, DNS, TLS, or egress firewall difference | Check uname -m, image logs, DNS resolution, outbound HTTPS, and the target’s response from inside the container. |
Deploy the scraper on a Linux VPS
1. Prepare the host
- Create a dedicated deployment user and a directory such as
/opt/puppeteer-scraper. - Install Docker from the distribution’s supported channel, enable its service, and test an unprivileged deployment workflow.
- Allow only SSH from your administration network and the application’s required outbound traffic. Do not expose the Docker API, Chrome debugging port, or an internal health port to the public internet.
- Store source, Compose files, and deployment notes in version control. Keep
dataand logs on controlled volumes.
2. Use Compose for repeatable settings
services:
scraper:
build: .
init: true
cap_add:
- SYS_ADMIN
shm_size: "2g"
restart: unless-stopped
env_file:
- .env
volumes:
- ./data:/app/data
- ./logs:/app/logs
read_only: true
tmpfs:
- /tmp:size=512m
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
Review the read-only setting against your image and browser profile behavior; add writable mounts rather than disabling the sandbox or making the entire filesystem writable. The restart policy handles an unexpected process exit, but it does not replace alerting: a job that repeatedly fails with exit code zero can still be unhealthy.
3. Inject secrets at runtime
Keep API keys, cookies, database passwords, and proxy credentials out of Git, Docker layers, and command history. Use a root-readable environment file with restrictive permissions, a VPS secret store, or your deployment system’s secret injection. Rotate credentials, redact them from logs, and never include full authorization headers in screenshots or HTML captures.
Rank #4
- 【Softer and More Comfortable】Vaydeer wrist rest has unique diamond pattern, which is the combination of softness and aesthetics. The materials of wrist rest are improved into higher quality memory foam and covered with silky smooth lycra. The computer wrist rest makes you as comfortable and cushiony as like rest your wrists on clouds.
- 【Ergonomic Wrist Saver】The wrist rests for keyboard and mouse comes with a 17.32×3.15×0.83 inch keyboard wrist pad and a 5.94×3.15×0.83 inch mouse wrist support. Based on ergonomic design, the unique concave shape is the perfect fit for your wrist joints. The wrist rest pad fits most computer keyboards and laptops, improve hand and wrist posture, release your wrist and arm stress.
- 【Non-Slip Rubber Bottom】Featuring an anti-skid silicone base on the bottom, this wrist keyboard support stays firmly in place on your desk, preventing the padding from sliding around, ensuring stable and consistent wrist support during extended computer sessions.
- 【Better Experience & Pain Relief】Our keyboard arm rest is beneficial to alleviate the soreness caused by direct contact and friction between your arm and a hard desk surface, reducing the risk of wrist fatigue or carpal tunnel. The soft texture of memory foam can evenly distribute the pressure around your wrists and provide good support with just enough give.
- 【Helpful in Multiple Scenarios】Whether you're working, studying, writing, typing, gaming, this keyboard and mouse rest combo is an essential accessory to add comfort and support to your hands and wrists. It’s also a great gift for men, women, family, friend, coworker, gamer, teacher, etc.
4. Schedule jobs safely
A host-level cron entry is simple for periodic collection. Prevent overlapping runs with a lock and send output to the container logger:
flock -n /var/lock/puppeteer-scraper.lock
docker compose --project-directory /opt/puppeteer-scraper run --rm scraper
Place that command in the host’s crontab at the required interval. A systemd timer is preferable when you need explicit dependencies, missed-run handling, resource limits, and journal integration. Whichever scheduler you choose, set a timeout, record a heartbeat only after successful validation, and alert when a run is late or repeatedly unsuccessful.
Recommended Free Tools
5. Persist results and diagnostics
JSON Lines is convenient for append-only collection, but production systems should define a deduplication key, schema version, retention period, and recovery procedure. Write to a temporary file and rename it when producing a complete batch, or use a transactional database when partial files would be harmful. Keep screenshots, HTML, and trace files only for failed jobs, cap their size, and delete them after the investigation window.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Make the worker observable before scaling
Emit one structured log event per attempt with a job identifier, target hostname, start and end time, duration, HTTP outcome when available, row count, retry number, and a sanitized error class. Track:
- success and failure counts by target;
- navigation, selector-wait, extraction, and browser-launch durations;
- CPU, resident memory, container restarts, file descriptors, and disk use;
/dev/shmconsumption and Chrome disconnects;- queue depth and oldest waiting job;
- HTTP status patterns, throttling responses, and TLS or DNS failures.
Add a lightweight health endpoint only if your process is long-lived. It should report process liveness separately from the age of the last successful collection. A reverse proxy or monitoring agent can poll it over a private interface. Do not expose a debugging endpoint that accepts arbitrary JavaScript or browser commands.
Best Value
- 【No Drill Mounted】Cable management tray can be assembled in as little as 3 minutes or less-simply. Side clips easily clampe the edge of desk, pass through the holes on the sides, and secure excess cables with baskets. Desk cable management supports inward or outward installation to meet your needs in different scenarios, and provides you with great convenience when collecting and organizing wires.
- 【Rubber Pad Protects Desk】Wire organizer under desk built-in soft rubber pads on the clamp protect your desk from scratches, so you will not damage your furniture or office.
- 【Sturdy and Beautiful】Cord management under desk is made of high-quality carbon steel and holds about 15 lbs. The wire basket has 2 holes on each side of the tray to enable your cables to pass freely. Cable baskets are suitable for desk thickness use from 0.4" to 2.4".
- 【Space Saving & Keep Organized】Desk cable management tray holds all your power cords, outlet strips, USB hubs and computer transformers hidden from your feet, and the data cables will not enter the vacuum cleaner to keep your desk clean and tidy. Desk wire organizer is also suitable for use in the kitchen and outdoors.
- 【Reduce Safety Risks】Cable tray under desk keeps all plugs away from your kids, no more worry about tripping. Using 2 holes wire tray saves extra space, helps you easily cabling and wire protection. The mesh design is not easy to accumulate dust, but avoids safety accidents caused by messy wires.
Control concurrency, queues, and timeouts
Start with one browser and one page. Increase limits one at a time while observing the VPS and target site. Give every navigation, selector wait, job, and queue item a deadline. On timeout, close the page, record the URL and stage, and retry only when the failure is plausibly transient. Use exponential backoff with a cap and add jitter so scheduled workers do not synchronize.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesBound the queue length. When it is full, reject or defer new work rather than allowing unbounded memory growth. Apply per-host rate limits and a global limit, and keep sessions isolated when cookies or authentication contexts must not leak between jobs. Graceful shutdown should stop accepting new jobs, allow active pages a short deadline, close pages, close the browser, flush logs, and exit with a meaningful status.
Embedded Puppeteer versus Browserless self-hosting
Embedded Puppeteer launches and manages the browser in the same service as your scraper. Browserless self-hosting runs a browser service that your code reaches through Puppeteer’s WebSocket connection or its REST APIs. The better choice depends on whether browser lifecycle management or application-level control is your main burden.
| Decision area | Embedded Puppeteer container | Browserless self-hosted image |
|---|---|---|
| Architecture | One application owns browser launch, pages, retries, and extraction. | A separate browser endpoint accepts sessions from one or more clients. |
| Image maintenance | You maintain the application image and either use the official Puppeteer image or maintain a custom browser image. | You maintain the Browserless image, its configuration, and the client application. |
| Version control | Direct control over the Node, Puppeteer, and browser combination you test. | Browser version follows the selected Browserless image; test the WebSocket client against that image. |
| Sandbox and privilege | Configure SYS_ADMIN, init handling, writable paths, and sandbox behavior in your container. |
Configure the same host-level security concerns for the browser service, then secure its network endpoint. |
| Shared memory | Set a suitable --shm-size; 64 MB is commonly too small for loaded pages. |
Its documentation recommends shm_size: "2g" or --shm-size=2g because Docker’s 64 MB default can crash Chrome under load. |
| Concurrency and queues | Implement a queue, worker limit, and back-pressure in your application. | Configuration includes CONCURRENT, QUEUED, TIMEOUT, and a Compose restart policy; choose values from measured VPS capacity and target limits. |
| Authentication | Protect your application and any internal job API using your normal secret mechanism. | Set TOKEN before exposing the service. Without it, every endpoint is unauthenticated, including /function, which executes arbitrary Puppeteer code from the request body. |
| Observability | You choose logs, metrics, health checks, screenshots, and traces. | Provides health checks, sessions, and a debugger, while your scraper still needs business-level success metrics. |
| API surface | Direct JavaScript control with no extra network hop. | Remote Puppeteer WebSocket connectivity and REST APIs can simplify multi-language clients and shared browser access. |
| Proxy features | Bring and secure a permitted proxy integration yourself. | Documentation describes residential routing at 6 units per MB and datacenter routing at 2 units per MB, plus country, city, and sticky-session options. These are vendor pricing units and may change. |
| Feature boundary | You build only the automation features your policy permits. | The open-source image does not include stealth, CAPTCHA solving, or advanced unblock routes; those are cloud or enterprise features. |
| Operating cost | Fewer moving parts and one service to run, but your team owns browser operations. | Additional service resources and maintenance, offset by built-in queueing, APIs, health checks, and debugging. Any hosted plan, proxy usage, bandwidth, and VPS cost must be evaluated separately. |
Choose embedded Puppeteer when one application controls a predictable workload and you want the fewest components. Choose self-hosted Browserless when several clients need a standard remote endpoint, shared sessions, or built-in queue and debugger features. In either model, authentication, rate limiting, shared-memory sizing, and legal permission remain your responsibility.
When a custom Dockerfile is unavoidable
Some managed container platforms provide a Node runtime without the operating-system packages required by Headless Chrome. Google Cloud Run’s default Node runtime is one documented example; use a custom Dockerfile there rather than assuming the platform image can launch Chrome. The same rule applies to any VPS or service where a plain Node image lacks the libraries listed in Puppeteer’s system requirements.
Build the image in a repeatable pipeline, run a browser smoke test during deployment, and retain the image digest with the release record. Test navigation, selector waits, downloads or PDFs if used, shutdown, and the target’s representative content before switching the scheduler to the new release.
Quick Recap
Production checklist
- Written permission, terms, robots guidance, privacy review, and a defined retention period.
- Node 22.12 or newer and an exact Puppeteer dependency recorded in the lockfile.
- Chrome and Puppeteer versions tested together on the VPS architecture.
- Official image with
--initand--cap-add=SYS_ADMIN, or a custom image with documented equivalent behavior. - Writable temporary/profile paths and a deliberate read-only filesystem policy.
/dev/shmsized for measured load; begin testing with 2 GB and adjust.- Explicit navigation and selector waits, validation, bounded retries, backoff, and sanitized structured logs.
- Graceful page and browser closure, health or heartbeat reporting, and alerting on stale success.
- Bounded concurrency, queue length, per-target rate limits, and job deadlines.
- Firewall rules, private Docker control plane, runtime-injected secrets, and rotated credentials.
- Persistent result storage, deduplication, log rotation, diagnostic-artifact limits, and a restore procedure.
- Scheduler locking so two runs cannot consume the same resources unintentionally.
- Documented rollback to the previous image and lockfile when a browser update changes page behavior.
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.

