ScreenshotNeo

BlogHow-to

Using a Screenshot API from the Command Line

Capture website screenshots from your shell with Playwright, curl, or a hosted API, including full-page CI workflows and troubleshooting.

By the ScreenshotNeo team1 October 20268 min read

Fastest answer: use Playwright CLI when you want a local browser, or call a hosted screenshot API with curl when you want one authenticated HTTP request. For a full-page local capture:

npm install -g @playwright/cli@latest
playwright-cli open https://example.com
playwright-cli screenshot --full-page --filename=example.png

For a hosted service, send the URL, output format and capture options in an HTTP request. Keep API keys in environment variables or your CI secret store.

1. Choose a command-line screenshot workflow

Route Best for What runs Trade-off
Playwright CLI Local development and CI with browser control A browser process on your machine or runner You manage browser installation, resources and updates
Hosted REST API Scripts that should make an HTTP request Rendering infrastructure operated by the provider You manage authentication, quotas and request failures
shot-scraper Python-oriented shell pipelines Playwright through a Python command-line utility Python and browser dependencies are still local

Playwright’s screenshot command supports viewport or element capture, full-page output, a filename, PNG/JPEG/WebP output and high-resolution mode. Its Page API also exposes fullPage, quality and scale options. The Playwright screenshot documentation is the reference for browser-side capture. shot-scraper is documented as a Python command-line utility built on Playwright.

2. Capture a screenshot locally with Playwright CLI

Install and capture the viewport

npm install -g @playwright/cli@latest
playwright-cli open https://example.com
playwright-cli screenshot --filename=example.png

The default capture is the current viewport. Anything below the fold may be absent.

Capture the complete page

playwright-cli open https://example.com
playwright-cli screenshot --full-page --filename=example-full.png

Use full-page mode for documentation pages, landing pages and regression snapshots where content below the viewport matters.

Choose the image format and resolution

# PNG
playwright-cli screenshot --type=png --filename=page.png

# JPEG
playwright-cli screenshot --type=jpeg --filename=page.jpg

# WebP
playwright-cli screenshot --type=webp --filename=page.webp

# High-resolution capture
playwright-cli screenshot --hires --filename=page-hires.png

PNG is lossless and useful for text comparison. JPEG is smaller for photographic pages. WebP is useful when your downstream system accepts it. Pick the format before you build CI assertions around file size or visual diffs.

Capture one element

Open the page, target the element with the CLI’s locator workflow, then run screenshot for that element. Element capture is useful when a page contains a chart, card or component that should be tested independently. If you need a stable programmatic selector, use the Playwright Page API:

node - <<'NODE'
const { chromium } = require('playwright');
(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com', { waitUntil: 'networkidle' });
  await page.locator('main').screenshot({ path: 'main.png' });
  await browser.close();
})();
NODE

3. Run Playwright in CI

A CI job needs Node.js, the Playwright package and the browsers required by your project. Cache dependencies where your CI platform supports it, and pin versions so a browser update does not silently change pixels.

set -eu
npm install -g @playwright/cli@latest
playwright-cli open "$TARGET_URL"
playwright-cli screenshot --full-page --type=png --filename=artifacts/page.png

Set TARGET_URL in the job environment. Store the generated file as a CI artifact. For visual regression, compare images at a fixed viewport, device scale and page state; animations, timestamps, ads and personalized content can otherwise create diffs.

4. Call a hosted screenshot API with curl

A hosted API removes the local browser process from your script. Screenshot API’s documentation shows an authenticated POST request with a JSON body:

export SCREENSHOT_API_KEY='your-key'
curl -X POST "https://api.screenshot-api.org/api/v1/screenshot" \
  -H "Authorization: Bearer $SCREENSHOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com","format":"png","fullPage":false}' \
  -o example.png

The service documentation also describes query-parameter and X-API-Key authentication, GET and POST methods, PNG/JPEG/WebP/PDF output, redirects with redirect=1, and a batch endpoint at /api/v1/screenshot/batch. Follow the provider’s response mode: a request may return image/PDF bytes, JSON, or a redirect depending on its documented options.

5. Use Python or Node.js for a shell pipeline

Python with a hosted API

import os
import requests

api_key = os.environ["SCREENSHOT_API_KEY"]
response = requests.post(
    "https://api.screenshot-api.org/api/v1/screenshot",
    headers={
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json",
    },
    json={"url": "https://example.com", "format": "png", "fullPage": True},
    timeout=90,
)
response.raise_for_status()
with open("example.png", "wb") as image:
    image.write(response.content)

Node.js with fetch

const apiKey = process.env.SCREENSHOT_API_KEY;
const response = await fetch('https://api.screenshot-api.org/api/v1/screenshot', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    url: 'https://example.com',
    format: 'png',
    fullPage: true
  })
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = Buffer.from(await response.arrayBuffer());
require('fs').writeFileSync('example.png', data);

6. Configure the capture deliberately

Need Local approach Hosted API approach
Below-the-fold content --full-page Set the provider’s fullPage option
Output type --type=png|jpeg|webp Set format; PDF is available where documented
Specific component Element locator or Page API locator screenshot Use the provider’s selector or element option when available
High resolution --hires, or Page API scale Use the provider’s viewport and scale parameters
Many URLs Loop with bounded concurrency Use the documented batch endpoint when available

Wait for the page state your screenshot represents. A network-idle wait can still leave delayed JavaScript, lazy images or consent dialogs. For deterministic output, disable animations in your own test CSS, use a fixed viewport, and provide a stable authenticated test page.

7. Or skip the browser setup

ScreenshotNeo is a hosted website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP or PDF. The API accepts the parameter names used by other screenshot APIs, making migration easier. See the ScreenshotNeo API documentation for the complete option list.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
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}`);

Before capture, ScreenshotNeo can accept cookie and consent banners and remove more than 60 known consent platforms, newsletter popups and chat widgets; each step can be turned off. Failed bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. It also provides full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF controls, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API and an OpenAPI specification. Its MCP server exposes take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients.

There are 1,000 free shots each month with no card. Paid plans start at $5 for 3,000 shots; yearly billing gives two months free, and every feature is on every plan. Create a free ScreenshotNeo account.

8. Reliability, performance and cost

Reliability checklist

  • Set an explicit HTTP timeout and handle non-2xx responses.
  • Retry transient network and server errors with exponential backoff and a maximum attempt count.
  • Do not retry authentication errors or invalid URLs without fixing the request.
  • Record the target URL, capture options, response status and output checksum.
  • Use idempotent job identifiers when the provider supports asynchronous jobs.

Performance checklist

  • Use viewport capture when below-the-fold content is unnecessary.
  • Choose WebP or JPEG when smaller files reduce transfer time.
  • Limit concurrency so your CI runner, network and provider quota are not overwhelmed.
  • Reuse a browser process for local batches instead of launching one browser per URL.
  • Use caching only when stale output is acceptable; otherwise include a cache-busting URL or disable caching.

Cost checklist

Local Playwright has no hosted per-shot charge, but your team pays for runner time, browser downloads and maintenance. Hosted APIs trade that setup for usage pricing and quotas. Count full-page, PDF and batch operations according to each provider’s billing rules. With ScreenshotNeo, only clean shots are billed; bot checks, blank pages, timeouts, failed loads and cache hits are free and identified in the response headers.

9. Troubleshooting

Symptom Likely cause Fix
playwright-cli: command not found The CLI is not installed globally or is not on PATH. Run npm install -g @playwright/cli@latest, then open a new shell.
Browser executable missing Browser dependencies were not installed on the runner. Install the browsers required by your Playwright setup and cache them in CI.
Screenshot is only the top of the page Viewport capture is the default. Add --full-page or the API’s fullPage option.
Lazy images are blank Capture happened before scrolling or image loading completed. Wait for the relevant selector, scroll the page, or use a service that loads lazy images during full-page capture.
401 or 403 from an API Missing, expired or incorrectly formatted credentials. Read the key from a secret, verify the required bearer/query/header format and check the account.
HTML or JSON saved as an image The response is an error document or redirect rather than image bytes. Inspect status and Content-Type before writing the body to a file.
Intermittent timeouts The target is slow, blocked, or waiting on a resource that never completes. Increase the client timeout, add bounded retries, and use explicit waits instead of waiting forever for network idle.
Visual diffs on unchanged code Animations, ads, timestamps, fonts or personalized content changed. Freeze test data, disable animations, use a fixed viewport and block unstable resources.
Secrets appear in CI logs The key was placed directly in a command or debug output. Use masked environment variables and avoid printing full request URLs containing query credentials.

10. FAQ

Can I take a screenshot without installing a browser?

Yes. Use a hosted screenshot API with curl. A local Playwright or shot-scraper workflow requires browser dependencies.

Why is full-page capture different from a tall viewport?

Full-page capture renders and stitches content beyond the initial viewport. A normal screenshot captures only what is visible at the current viewport.

Which format should I use?

Use PNG for lossless visual comparisons, JPEG for photographic pages and WebP when your delivery stack supports it and smaller files are useful.

How should I protect an API key?

Store it in an environment variable or CI secret manager. Never commit it to a script, shell history shared with others or a public repository.

Can an AI agent request screenshots?

Yes. ScreenshotNeo includes an MCP server with take_screenshot, get_page_info and capture_pdf tools for MCP clients such as Claude and Cursor.