DriversRecommendedOutdated drivers can make a good PC feel brokenScan driver issues before chasing fixes manually.Scan NowOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run Scan×
Skip to content
browser automation

How to Ship Browser Automation to Users with Convex

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use Convex as the control plane, not the browser. Your Convex functions should authenticate a request, record a job, and coordinate its state. Run Playwright in a Node-capable worker or connect to a managed browser service, then write the result back to Convex. This separation avoids trying to launch Chromium inside Convex HTTP actions, which use the Fetch API environment and do not provide Node-specific browser APIs.

The production architecture

A reliable system has four parts:

  1. Frontend: the user starts an automation and watches its status through Convex.
  2. Convex: authenticated mutations create jobs; queries expose status; actions or HTTP actions dispatch work and persist results.
  3. Browser runner: a worker you operate or a remote browser provider runs Playwright.
  4. Target application: the site your automation is allowed to visit.

The request path should be asynchronous for anything that can exceed a short interactive request: accept the request, create a durable job, execute it in the worker, and update the job to succeeded or failed. Store a useful error message and timestamps so users can retry without losing history.

Why Convex should not launch Chromium

Convex HTTP actions expose HTTP endpoints at your deployment’s .convex.site address. They receive Fetch API Request objects and return Response objects; they can call Convex queries, mutations, and actions. They run in the same managed environment as other Convex functions, however, and do not expose Node-specific APIs. Treat an HTTP action as an ingress and coordination boundary, not as a Chromium host.

HTTP actions also have a documented 20 MB request and response limit, are not automatically retried on errors, and are unnecessary when a caller you control can use a Convex client directly. These constraints favor a job record and a separate runner instead of keeping a browser open during an HTTP request.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose where Playwright runs

Option What you operate Important trade-offs
Own Node worker A worker image containing the Playwright package, matching browser binaries, and system dependencies. You control isolation, updates, scaling, and image size. Playwright browser downloads can add hundreds of megabytes; its documentation gives example footprints of 281 MB for Chromium and 187 MB for Firefox.
Managed browser Your application connects to a vendor-hosted browser over a supported protocol. Less browser maintenance, but verify credentials, session limits, regional availability, pricing, and protocol support for your exact scripts.
Self-hosted browser service A browser endpoint, such as a documented Browserless Docker deployment, plus its networking and monitoring. You own upgrades, capacity, incident response, and authentication. A reachable endpoint without a token can expose browser-control operations, including an endpoint that can run supplied code.

Browserless documents Playwright connections by replacing chromium.launch() with chromium.connectOverCDP(). CDP supports most scripts, but Browserless identifies features and browser choices that require Playwright’s native protocol. Confirm compatibility before committing to a remote provider.

Model a durable Convex job

Keep the browser payload small: store a URL, an allow-listed operation, and parameters in Convex, rather than uploading screenshots or arbitrary scripts through an HTTP action.

import { mutation, query } from "./_generated/server";
import { v } from "convex/values";

export const create = mutation({
  args: {
    url: v.string(),
    operation: v.union(v.literal("capture"), v.literal("extract")),
  },
  handler: async (ctx, args) => {
    const identity = await ctx.auth.getUserIdentity();
    if (!identity) throw new Error("Authentication required");

    // Validate the URL and operation against your own policy here.
    return await ctx.db.insert("browserJobs", {
      userId: identity.subject,
      url: args.url,
      operation: args.operation,
      status: "queued",
      createdAt: Date.now(),
    });
  },
});

export const get = query({
  args: { id: v.id("browserJobs") },
  handler: async (ctx, args) => {
    const job = await ctx.db.get(args.id);
    const identity = await ctx.auth.getUserIdentity();
    if (!job || !identity || job.userId !== identity.subject) return null;
    return job;
  },
});

The worker should claim a queued job atomically (for example, changing it to running with a lease), perform the permitted steps, and call a server-side Convex mutation to save the result. Add a lease expiration so a crashed worker does not leave a job running forever. Enforce per-user quotas, destination allow-lists, navigation and total execution timeouts, and maximum output sizes.

Install and run Playwright in your worker

Install a Playwright version and its browsers together so the binary matches the package. The installation command and dependency setup belong in the worker image, not in a Convex function.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
npm install playwright
npx playwright install --with-deps chromium

A minimal runner can look like this:

import { chromium } from "playwright";

export async function runCapture(url) {
  const browser = await chromium.launch({ headless: true });
  try {
    const context = await browser.newContext({
      viewport: { width: 1440, height: 900 },
      deviceScaleFactor: 1,
    });
    const page = await context.newPage();
    await page.goto(url, { waitUntil: "networkidle", timeout: 30_000 });
    return await page.screenshot({ fullPage: true, type: "png" });
  } finally {
    await browser.close();
  }
}

In production, do not accept JavaScript from users and evaluate it blindly. Map a small set of named operations to code you reviewed. Close every browser and context in a finally block, cap concurrency, and reject private-network destinations if users can submit arbitrary URLs.

Connect to a managed browser

When a provider supplies a CDP endpoint, keep its token in the worker environment and connect from Node:

import { chromium } from "playwright";

const browser = await chromium.connectOverCDP(
  `https://production-sfo.browserless.io?token=${process.env.BROWSER_TOKEN}`
);
try {
  const context = await browser.newContext();
  const page = await context.newPage();
  await page.goto("https://example.com", { waitUntil: "domcontentloaded" });
  const title = await page.title();
  console.log(title);
} finally {
  await browser.close();
}

The hostname and protocol in this example are illustrative of the connection pattern; use the endpoint supplied by your provider. Check whether your script needs native Playwright protocol features before choosing CDP.

Deploy Convex safely

Development, preview, staging, and production

Convex provides a development deployment for each team member and one shared production deployment per project. Use a preview deployment for branch validation. For a longer-lived staging environment, use a separate Convex project rather than treating production as a test database.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Deploy backend changes with:

npx convex deploy

The CLI typechecks, generates code, bundles functions, and pushes functions, indexes, and schema. In CI, use a deployment key and select the intended production or preview deployment through the CI environment. Your frontend host remains a separate pipeline; configure its Convex client with the production deployment URL only after the backend is ready.

Keep releases backwards compatible

Convex’s production guidance says functions should be backwards compatible. An older website bundle may still call the backend after a deploy, and scheduled functions execute the currently deployed code with the arguments captured when they were scheduled. Add fields rather than abruptly renaming them, accept old argument shapes during a migration, and leave compatibility code in place until queued jobs and old clients have drained.

Store browser credentials as deployment secrets

Convex environment variables are configured per deployment, so development, preview, staging, and production can use different browser-provider credentials. Declare expected variables in convex/convex.config.ts when you want typed access and deploy-time validation. Current documented limits are 512 variables per deployment, 512 KiB total variable name/value capacity, and 8 KiB for one value.

  • Put the managed-browser token or self-hosted endpoint credential in trusted Convex or worker configuration.
  • Never put that token in a public frontend environment variable or ship it in JavaScript.
  • Use separate credentials per environment and rotate them without reusing development tokens in production.
  • Use CONVEX_CLOUD_URL for Convex clients and CONVEX_SITE_URL when configuring HTTP actions, as documented by Convex.

If the worker is outside Convex, give it a narrowly scoped server credential that can update only the jobs it is authorized to process. Authenticate every user request before creating a job; do not expose a browser-control endpoint directly to untrusted callers.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Expose an HTTP endpoint when an external caller needs it

For webhooks or an external queue, an HTTP action can validate a signed request, create a Convex job, and return a small JSON acknowledgment. Keep the response under the 20 MB limit and implement your own retry and idempotency keys because HTTP actions are not automatically retried. A caller you own should normally use the Convex client instead of adding an HTTP layer solely to call a function.

Return a job identifier immediately. Let the frontend subscribe to the job query, or let a webhook report completion. Do not send a full PDF or screenshot through the action when a storage reference or signed download URL will do.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server when your requirement is a clean capture rather than custom Playwright interaction. One GET request returns PNG, JPEG, WebP, or a PDF. Before capture it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response reports the page verdict and billing status in X-Page-Verdict and X-Billed headers.

It also supports full-page screenshots with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets or custom viewports, retina scale, PDF paper size/margins/landscape/page ranges, HTML/CSS-to-image, custom CSS and JavaScript, pre-capture clicks, hidden selectors, selector/delay/network-idle waits, request and resource blocking, custom headers/cookies/user agents/Authorization, timezone and geolocation, transparent backgrounds, resizing, TTL caching, signed public image links, asynchronous jobs with signed webhooks, bulk capture of 100 URLs per call, a usage API, an OpenAPI specification, and parameter names compatible with other screenshot APIs. Its MCP server provides take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use its API key only on trusted server infrastructure. The following call captures Stripe as WebP:

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 documentation for option names and response behavior. Equivalent clients are:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is on every plan, and yearly billing provides two months free. Create a free ScreenshotNeo account to try it.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, reliability, and cost decisions

  • Cold starts and browser launch: keep a worker warm when latency matters, but recycle browsers periodically to contain leaks.
  • Concurrency: set a fixed number of browser contexts per worker based on memory, then queue excess jobs instead of allowing unbounded launches.
  • Timeouts: use separate navigation, selector-wait, and total-job deadlines. Record which deadline fired.
  • Retries: retry transient provider or network failures with an idempotency key; do not repeat non-idempotent user actions without a checkpoint.
  • Payloads: store large artifacts in object storage and save metadata or references in Convex. Respect the 20 MB HTTP action limit.
  • Cost: measure browser minutes, worker memory, storage, provider sessions, and screenshot volume separately. Provider prices and quotas vary; verify the plan for your workload rather than assuming a published limit.

Troubleshooting

“Cannot find module” or missing browser executable

The worker has the Playwright package but not its matching browser binary or system dependencies. Run the Playwright browser-install command during image build and pin compatible package and browser versions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Convex function cannot launch Chromium

That is an architectural mismatch: move Playwright to the Node worker or remote browser and let Convex create and track the job.

HTTP action returns a timeout or oversized response

Return an acknowledgment and job ID, then process asynchronously. Save the artifact elsewhere and persist a reference, not the binary, in the action response.

Jobs remain “running” after a crash

Use a lease with an expiration timestamp. A reaper or the next worker pass can move expired leases back to queued with an attempt count.

Old clients fail after deployment

Keep function arguments and scheduled-job data compatible with the previous release. Deploy additive schema and behavior first, migrate callers, then remove compatibility code.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Remote connection is rejected

Check the token, endpoint protocol, browser choice, and whether your script requires native Playwright protocol features that the provider’s CDP path does not implement.

Credentials appear in browser network logs

Move them out of frontend configuration. Store them in per-deployment Convex or worker secrets and proxy the operation through an authenticated server boundary.

Pre-launch checklist

  • Playwright and browser binaries are version-matched in the worker image.
  • Every job has authentication, authorization, a timeout, a lease, and an idempotency strategy.
  • User-supplied URLs and actions pass an allow-list and private-network checks.
  • Provider tokens are absent from frontend bundles and separated by deployment.
  • Preview or staging has been exercised before the shared production deployment.
  • Old clients and scheduled jobs remain compatible during rollout.
  • Artifacts, logs, failures, and billing-relevant provider responses are observable without exposing secrets.

FAQ

Can Convex run Playwright directly?

Not as the browser host. Use Convex for coordination and a Node-capable worker or remote browser for Playwright.

Should every automation request use an HTTP action?

No. A controlled frontend should call Convex through its client. Use an HTTP action for external callers, webhooks, or another integration boundary.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Is a separate Convex project required for staging?

It is the documented choice for longer-lived staging; preview deployments are suitable for branch validation.

Can I expose my self-hosted browser endpoint to users?

Do not expose it directly. Put an authenticated, authorized job service in front of it and configure endpoint authentication.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.