Visual regression testing lives or dies on capture stability. Self-hosted browsers in CI introduce the flakiness you're trying to detect: font availability differs per runner, browser versions drift, and parallel jobs fight for memory.
Capturing through an API gives every branch and every run the identical rendering environment. Your CI job sends URLs (or preview-deploy URLs), gets PNGs back, and runs the diff — no playwright install step, no browser cache, no runner snowflakes.
// e.g. GitHub Action step against a Vercel/Netlify preview URLconst pages = ["/", "/pricing", "/docs"];const shots = await Promise.all(pages.map((path) =>fetch("https://api.screenshotty.link/api/v1/screenshot", {method: "POST",headers: {"X-Api-Key": process.env.SCREENSHOTTY_API_KEY,"Content-Type": "application/json",},body: JSON.stringify({url: `${process.env.PREVIEW_URL}${path}`,viewport_width: 1280,viewport_height: 800,ready_event: "networkidle",adblock: true,}),}).then((r) => r.arrayBuffer())));// → diff against baselines with pixelmatch/odiff
Same Chrome, same fonts, same flags for baseline and candidate — diffs show your changes only.
ready_event, wait_ms, and scroll_to_bottom pin down lazy content before capture.
Capture individual components with CSS selectors for tighter, less noisy diffs.
Capture a whole page matrix concurrently; webhooks deliver results without blocking CI.
Inject css_code to disable animations (e.g. *, *::before, *::after { animation: none !important; transition: none !important; }) and pin dynamic content with javascript_code where needed.
No — it complements them. Keep interaction tests in your test runner; use API captures for the page-level visual layer where browser-infrastructure flakiness hurts most.
Yes. 100 screenshots per month free, no credit card required. Paid plans start at $9/month for 2,500 screenshots with $0.004 pay-as-you-go overage.
Yes — capture the same URL at multiple viewport sizes (or device presets) in parallel and diff each against its own baseline.