Cypress takes screenshots. So does a screenshot API. But they solve different problems at different layers of your stack, and picking the wrong one for your use case means either over-engineering a simple capture or losing the test automation context you actually need. I run screenshotrun (a screenshot API), so keep that in mind as you read. The technical differences below are verifiable against Cypress docs and screenshotrun's public API.
This comparison covers when cy.screenshot() is the right tool, when an API call makes more sense, where the two overlap — plus how to use both in the same workflow.
Different tools for different jobs
Cypress is a test framework. Screenshots are a side effect — you capture them during a test run to document state, debug failures, or feed into a visual regression plugin. The screenshot happens inside a browser that Cypress already controls, after Cypress has navigated to a page, logged in, clicked buttons, filled forms. That test context is the whole point.
A screenshot API is an HTTP endpoint. You send a URL (or raw HTML), set parameters for viewport, format, content blocking — and get back an image. No test runner, no browser to manage, no application state to set up. The API handles the browser internally. Your code never touches it.
Cypress answers "what does my app look like after step 7 of this test?" A screenshot API answers "what does this URL look like right now?"
cy.screenshot() capabilities and constraints
Cypress gives you three capture modes: viewport (visible area only), fullPage (scrolls the entire document), runner (includes the Cypress command log sidebar). The default is fullPage.
// Cypress screenshot — basic usage
cy.screenshot('homepage-after-login')
// Element-level capture with blackout
cy.get('.dashboard-panel').screenshot('panel', {
blackout: ['.user-email', '.api-key'],
padding: 10
})
The options are focused on testing needs. blackout covers sensitive selectors with black rectangles — useful for masking PII in test artifacts. disableTimersAndAnimations freezes CSS animations and JavaScript timers so the capture is deterministic. onBeforeScreenshot and onAfterScreenshot callbacks let you manipulate the page before and after capture without affecting subsequent test steps.
But the constraints matter too. Output is PNG only — not JPEG, WebP, AVIF, or PDF. The default viewport in headless mode is 1280x720, and Cypress crops everything beyond screen edges. Full-page capture stitches vertical scrolls together, which causes problems with sticky headers, smooth scroll CSS, pages where html or body have height: 100%. Horizontal scrolling pages only capture the first viewport width. And element screenshots fail outright if the selector matches more than one element.
Performance overhead is real. Developers on the Cypress GitHub reported screenshot operations adding 2-7 seconds each, depending on page complexity and display DPI. Across a suite of 200 tests with 2-3 screenshots per test, that overhead adds 15-30 minutes to the CI pipeline.
What a screenshot API handles differently
A screenshot API skips the test context entirely. No test runner, no assertions, no application state management. You trade that control for simplicity and output flexibility.
curl "https://api.screenshotrun.com/v1/screenshots/capture?url=https://example.com&format=webp&full_page=true&block_ads=true" \
-H "Authorization: Bearer YOUR_API_KEY"
One HTTP call, one image back. The API manages the headless browser internally — spins up a fresh Chromium instance, loads the URL, waits for the page to settle, captures, tears down. Your server never allocates memory for a browser process.
The output flexibility is where APIs pull ahead for non-testing use cases. screenshotrun returns any of six formats (PNG, JPEG, WebP, AVIF, TIFF, PDF) from the same endpoint. Content blocking (ads, cookie banners, chat widgets) is built in via boolean parameters. Retina capture, dark mode emulation, geolocation, stealth mode for bot-protected sites — all controlled through the request. Cypress has no equivalent for any of these because they're outside the scope of test automation.
Side-by-side breakdown
| Capability | Cypress cy.screenshot() | screenshotrun API |
|---|---|---|
| Primary purpose | Test documentation / visual regression | On-demand URL capture |
| Requires browser setup | Yes (Cypress-managed) | No (API-managed) |
| Application state control | Full (login, navigate, click, type) | Limited (URL + headers + cookies) |
| Output formats | PNG only | PNG, JPEG, WebP, AVIF, TIFF, PDF |
| Full-page capture | Yes (vertical stitching, has edge cases) | Yes (auto-scroll, lazy image loading) |
| Element-level capture | Yes (single element only) | Yes (selector parameter) |
| Retina / 2x output | No (matches screen DPI) | Yes, all plans |
| Dark mode | Only if app supports it + manual toggle | Yes, via parameter |
| Ad/cookie/chat blocking | No (must handle manually in tests) | Yes, boolean toggles |
| Sensitive data masking | Yes (blackout selectors) |
Yes (hide_selectors) |
| CSS/JS injection | Via test code (full control) | Yes, via parameters |
| Stealth mode | No | Yes, all plans |
| Geolocation | No built-in support | Yes, configurable |
| Webhook delivery | No | Yes |
| PDF generation | No | Yes, same endpoint |
| Parallel capture at scale | Requires multiple CI runners | Built-in (API handles concurrency) |
| Cost | Free (open source) + CI infrastructure | Free tier (200/mo) + paid plans from $9/mo |
| Visual regression testing | Via plugins (percy, applitools, etc.) | Not built in (capture only) |
When Cypress screenshots are the right choice
Cypress wins when you need the screenshot tied to application state that only a test runner can set up.
Visual regression testing is the obvious one. You log into your app, navigate to a specific page, expand a dropdown, scroll to a component — then capture exactly what the user would see at that moment. Tools like Percy or Applitools plug into Cypress to compare those captures across builds. The screenshot is evidence that your UI didn't break between commits. No external API can replicate that workflow because the API doesn't have access to your application's authenticated state.
Failure documentation is another strong case. Cypress automatically captures a screenshot when a test fails, including the command log. That artifact goes straight into your CI output, giving you a visual record of what the page looked like when the assertion broke. It's an automatic debug aid that requires zero additional setup.
The blackout option is genuinely useful for test artifacts that get shared or stored. Mask email addresses, API keys, financial data — the elements render as black rectangles in the PNG. If your test artifacts end up in a shared CI dashboard or get attached to bug reports, that masking prevents accidental data exposure.
If your screenshots exist purely to validate your own application's UI during test runs — Cypress is the tool that was designed for that job.
When a screenshot API makes more sense
The moment your screenshot requirement leaves the test runner context, Cypress becomes the wrong tool.
Capturing external URLs is the clearest example. If your app generates link previews, monitors competitor pages, creates social media cards from user-submitted URLs, produces PDF reports of third-party content — Cypress can't help. You'd need to write a standalone Puppeteer or Playwright script, manage browser instances, handle crashes, deal with memory leaks. Or make one API call.
# Capture any external URL — no browser management required
GET https://api.screenshotrun.com/v1/screenshots/capture?url=https://competitor.com&format=webp&block_ads=true&block_cookies=true
Authorization: Bearer YOUR_API_KEY
Scale is another dividing line. Cypress runs screenshots sequentially within a single browser instance. Capturing 500 URLs means 500 sequential operations inside a Cypress test — or splitting across multiple CI runners, each with its own browser overhead. A screenshot API handles that volume through parallel processing on the provider's infrastructure. Your server sends 500 HTTP requests. The API figures out the concurrency.
Format requirements matter too. Cypress outputs PNG only. If you need WebP for smaller file sizes in a web app, JPEG for email embeds, PDF for reports, AVIF for next-gen image optimization — you're either post-processing Cypress output through ImageMagick or using an API that supports the format natively. screenshotrun handles six output formats from one endpoint.
Production screenshot workflows (thumbnail generation, website monitoring, compliance captures, legal evidence) belong to an API. These run in production, not in test pipelines. They need to be reliable, stateless, format-flexible. Shoehorning Cypress into a production capture pipeline means running a test framework without tests — all overhead, no benefit.
Using both together
The two tools aren't mutually exclusive. A practical setup uses Cypress for what it does best (testing your own UI) while the API handles everything else.
One pattern that works well: Cypress tests validate your app's pages during CI. After deployment, a separate job calls the screenshot API to capture the live production pages — generating social media images, updating link previews in your database, or capturing competitor pages for monitoring. The Cypress screenshots live in your test artifacts. The API screenshots live wherever your application needs them.
// In your deployment pipeline (not Cypress)
const urls = ['https://yourapp.com/pricing', 'https://yourapp.com/features'];
for (const url of urls) {
const response = await fetch(
`https://api.screenshotrun.com/v1/screenshots/capture?url=${encodeURIComponent(url)}&format=webp&full_page=true`,
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
// Store the WebP image for social sharing cards
await saveToS3(url, await response.buffer());
}
Another pattern: your Cypress tests catch visual regressions in your UI. The screenshot API monitors external dependencies — third-party embeds, partner pages, sites you integrate with. If an external page changes layout and breaks your integration, the API-captured screenshots surface that change before your users notice.
Infrastructure and cost comparison
Cypress is open source and free to use. The screenshots themselves cost nothing. But the infrastructure to run Cypress at scale costs plenty. Each CI runner needs a browser (Chrome, Firefox, Electron), enough RAM to run it (Chromium alone claims 200+ MB per tab), and CPU time for rendering. Parallelizing across multiple runners multiplies that cost. Cypress Cloud (their paid dashboard service) adds hosted parallelization and screenshot storage, starting at $75/month for small teams.
A screenshot API externalizes all of that. screenshotrun's free tier covers 200 screenshots per month — no credit card, no expiration. Paid plans start at $9/month for 3,000 captures with every feature included. You're paying per screenshot instead of per CI minute, which makes costs predictable regardless of how complex the pages are or how long they take to render.
For teams already running Cypress for testing, the screenshot cost is effectively bundled into CI infrastructure you're paying for anyway. The API adds value when screenshot requirements extend beyond test runs — capturing external URLs, generating assets in production, handling format conversion, blocking ads on third-party pages.
Full-page capture: the edge cases
Both Cypress and screenshot APIs support full-page capture, but they handle it differently under the hood.
Cypress scrolls the viewport vertically and stitches captures together. This works for most pages but breaks down in specific scenarios. Pages with height: 100% on html or body confuse the scroll calculation. Sticky or fixed headers repeat in every stitched segment. Smooth scroll CSS (scroll-behavior: smooth) interferes with the scroll-capture timing. Horizontal scrolling pages only capture the leftmost viewport width — everything to the right gets clipped. These aren't theoretical problems; they're documented GitHub issues with dozens of affected developers.
screenshotrun uses a different approach. The browser scrolls through the entire page to trigger lazy-loaded images and Intersection Observer content, measures the full document height via document.documentElement.scrollHeight, then takes a single capture at that height. Sticky elements stay in place. Smooth scroll doesn't interfere because the capture happens after scrolling completes, not during. The result is one continuous image rather than stitched segments.
Neither approach is perfect for every page. Infinite scroll pages have no natural endpoint regardless of the tool. But for standard content pages with typical CSS layouts, the API approach produces fewer artifacts.
Picking the right tool
If your screenshots exist inside a test pipeline — capturing your own application's state after user interactions, feeding visual regression tools, documenting test failures — Cypress is the right tool. It was built for that workflow. An API can't replicate the test context that makes those screenshots meaningful.
If your screenshots exist outside a test pipeline — capturing external URLs, generating assets in production, converting pages to PDF, monitoring third-party sites, serving images to end users — a screenshot API is the right tool. Cypress wasn't built for that workflow, and forcing it into one means managing browser infrastructure that the API handles for you.
For a broader look at how screenshot APIs compare with other browser automation approaches, see the Puppeteer vs screenshot API and Playwright vs screenshot API comparisons. And if you're ready to test the API approach, the Node.js integration guide shows how to add screenshot capture to your existing codebase in under five minutes.
FAQ#
Technically yes, but it is not what Cypress was designed for. Cypress is a test framework for your own application — it expects to control navigation, authentication, and application state. Capturing arbitrary external URLs with Cypress means writing test boilerplate without any actual tests. A screenshot API handles external URLs natively with a single HTTP call, no browser setup required.
No. Cypress outputs PNG files exclusively. If you need WebP, JPEG, AVIF, or PDF output, you would need to convert the PNG after capture using a tool like ImageMagick or Sharp. screenshotrun supports six output formats from the same API endpoint, controlled by a single format parameter.
No — Cypress is better for visual regression testing. Visual regression requires capturing your application in specific states (logged in, after interactions, with test data), then comparing those captures across builds. Cypress can set up that state because it controls the browser. A screenshot API can only capture what a URL shows to an anonymous visitor, which is not enough for most visual regression workflows.
Yes, many teams do exactly that. Cypress handles test-pipeline screenshots (visual regression, failure documentation) while the API handles production screenshots (social media cards, link previews, competitor monitoring, PDF generation). The two tools complement each other because they operate at different layers of your stack.
Each Cypress screenshot adds roughly 2-7 seconds of overhead depending on page complexity and display DPI. A suite of 200 tests with 2-3 screenshots each can add 15-30 minutes to your CI pipeline. For high-volume screenshot needs outside testing, an API avoids that overhead entirely since the captures happen on the API provider infrastructure, not your CI runners.