Blog 7 min read

How to Automate Screenshots with cURL (No Code Required)

Capture website screenshots from the command line using cURL and a screenshot API. Covers batch captures, cron jobs, shell scripts, and CI/CD integration.

SnapRender Team
|

How to Automate Screenshots with cURL

You don't need Node.js, Python, or any programming language to automate website screenshots. A screenshot API and cURL give you everything you need from the command line.

This is useful for:

  • Capturing screenshots in shell scripts or cron jobs
  • Integrating screenshots into CI/CD pipelines
  • Quick one-off captures without writing code
  • Batch processing a list of URLs from a file

Getting Started

You need two things: cURL (installed by default on macOS and most Linux distributions) and a screenshot API key.

Sign up for SnapRender to get a free API key. The free tier includes 500 screenshots per month, no credit card required.

Set your API key as an environment variable so you don't have to repeat it:

export SNAPRENDER_KEY="sk_live_your_key_here"

Basic Screenshot

Capture a website and save it as a PNG:

curl -s "https://app.snap-render.com/v1/screenshot?url=https://example.com" \
  -H "X-API-Key: $SNAPRENDER_KEY" \
  -o screenshot.png

The API returns the raw image binary. The -o flag saves it to a file. -s suppresses the progress bar.

Choosing Output Format

The API supports PNG, JPEG, WebP, and PDF:

# JPEG (smaller file size)
curl -s "https://app.snap-render.com/v1/screenshot?url=https://example.com&format=jpeg&quality=85" \
  -H "X-API-Key: $SNAPRENDER_KEY" \
  -o screenshot.jpg

# WebP (best compression)
curl -s "https://app.snap-render.com/v1/screenshot?url=https://example.com&format=webp&quality=80" \
  -H "X-API-Key: $SNAPRENDER_KEY" \
  -o screenshot.webp

# PDF
curl -s "https://app.snap-render.com/v1/screenshot?url=https://example.com&format=pdf" \
  -H "X-API-Key: $SNAPRENDER_KEY" \
  -o page.pdf

Full-Page Capture

Capture the entire scrollable page, not just the visible viewport:

curl -s "https://app.snap-render.com/v1/screenshot?url=https://example.com&fullPage=true" \
  -H "X-API-Key: $SNAPRENDER_KEY" \
  -o fullpage.png

Custom Viewport Size

Set the browser window dimensions:

# Desktop HD
curl -s "https://app.snap-render.com/v1/screenshot?url=https://example.com&width=1920&height=1080" \
  -H "X-API-Key: $SNAPRENDER_KEY" \
  -o desktop.png

# Narrow mobile width
curl -s "https://app.snap-render.com/v1/screenshot?url=https://example.com&width=375&height=812" \
  -H "X-API-Key: $SNAPRENDER_KEY" \
  -o mobile.png

Device Emulation

Capture screenshots as they would appear on specific devices:

# iPhone 15 Pro
curl -s "https://app.snap-render.com/v1/screenshot?url=https://example.com&device=iphone_15_pro" \
  -H "X-API-Key: $SNAPRENDER_KEY" \
  -o iphone.png

# iPad Pro
curl -s "https://app.snap-render.com/v1/screenshot?url=https://example.com&device=ipad_pro" \
  -H "X-API-Key: $SNAPRENDER_KEY" \
  -o ipad.png

# Pixel 7
curl -s "https://app.snap-render.com/v1/screenshot?url=https://example.com&device=pixel_7" \
  -H "X-API-Key: $SNAPRENDER_KEY" \
  -o pixel.png

Device presets set the correct viewport size, device scale factor, and user agent string automatically.

Dark Mode

Capture pages with dark color scheme:

curl -s "https://app.snap-render.com/v1/screenshot?url=https://developer.mozilla.org&darkMode=true" \
  -H "X-API-Key: $SNAPRENDER_KEY" \
  -o dark.png

Clean Screenshots (No Ads, No Cookie Banners)

Ad blocking and cookie banner removal are enabled by default. You can control them explicitly:

curl -s "https://app.snap-render.com/v1/screenshot?url=https://www.bbc.com&blockAds=true&blockCookieBanners=true" \
  -H "X-API-Key: $SNAPRENDER_KEY" \
  -o clean.png

Hide Specific Elements

Remove elements by CSS selector before capturing:

# Hide the navigation bar
curl -s "https://app.snap-render.com/v1/screenshot?url=https://en.wikipedia.org/wiki/Screenshot&hideSelectors=%23mw-navigation" \
  -H "X-API-Key: $SNAPRENDER_KEY" \
  -o no-nav.png

URL-encode the selectors. %23 is #, %2C is , for separating multiple selectors.

Batch Screenshots from a File

For large-scale batch jobs (up to 50 URLs in one call with automatic rate limit handling), see the Batch API optimization guide. The examples below use simple cURL loops, which work well for smaller lists.

Create a text file with one URL per line:

https://example.com
https://github.com
https://stripe.com
https://developer.mozilla.org

Then loop through it:

while IFS= read -r url; do
  # Create filename from URL (strip protocol, replace / with -)
  filename=$(echo "$url" | sed 's|https\?://||; s|/|-|g; s|-$||').png

  echo "Capturing $url -> $filename"
  curl -s "https://app.snap-render.com/v1/screenshot?url=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$url', safe=''))")&format=png" \
    -H "X-API-Key: $SNAPRENDER_KEY" \
    -o "$filename"
done < urls.txt

Parallel Batch Captures

Speed up batch processing by running captures in parallel with xargs:

cat urls.txt | xargs -P 5 -I {} bash -c '
  url="{}"
  filename=$(echo "$url" | sed "s|https\?://||; s|/|-|g; s|-$||").png
  curl -s "https://app.snap-render.com/v1/screenshot?url=$url&format=png" \
    -H "X-API-Key: '"$SNAPRENDER_KEY"'" \
    -o "$filename"
  echo "Done: $filename"
'

-P 5 runs 5 captures simultaneously. Adjust based on your plan's burst rate limit.

Scheduled Screenshots with Cron

Capture a website every hour and save timestamped files:

# Edit crontab
crontab -e

Add this line:

0 * * * * curl -s "https://app.snap-render.com/v1/screenshot?url=https://example.com&format=png" -H "X-API-Key: sk_live_your_key" -o /home/user/screenshots/example-$(date +\%Y\%m\%d-\%H\%M).png

This captures example.com at the top of every hour and saves files like example-20260307-1400.png.

A More Robust Cron Script

For production use, create a script that handles errors:

#!/bin/bash
# screenshot-cron.sh

API_KEY="sk_live_your_key"
URL="https://example.com"
OUTPUT_DIR="/home/user/screenshots"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)

mkdir -p "$OUTPUT_DIR"

HTTP_CODE=$(curl -s -w "%{http_code}" \
  "https://app.snap-render.com/v1/screenshot?url=$URL&format=png" \
  -H "X-API-Key: $API_KEY" \
  -o "$OUTPUT_DIR/capture-$TIMESTAMP.png")

if [ "$HTTP_CODE" -ne 200 ]; then
  echo "$(date): Failed to capture $URL (HTTP $HTTP_CODE)" >> "$OUTPUT_DIR/errors.log"
  rm -f "$OUTPUT_DIR/capture-$TIMESTAMP.png"
fi

CI/CD Integration

GitHub Actions

Add screenshot captures to your CI pipeline:

- name: Capture screenshots
  env:
    SNAPRENDER_KEY: ${{ secrets.SNAPRENDER_KEY }}
  run: |
    curl -s "https://app.snap-render.com/v1/screenshot?url=https://staging.example.com&format=png&fullPage=true" \
      -H "X-API-Key: $SNAPRENDER_KEY" \
      -o screenshot.png

- name: Upload screenshot artifact
  uses: actions/upload-artifact@v4
  with:
    name: screenshots
    path: screenshot.png

Visual Diff in CI

Capture before and after screenshots to review visual changes:

#!/bin/bash
# visual-diff.sh - Run in CI after deploying to staging

PAGES=("/" "/pricing" "/docs" "/blog")
BASE_URL="https://staging.example.com"

for path in "${PAGES[@]}"; do
  safe_name=$(echo "$path" | sed 's|/|-|g; s|^-||; s|-$||')
  [ -z "$safe_name" ] && safe_name="home"

  curl -s "https://app.snap-render.com/v1/screenshot?url=${BASE_URL}${path}&format=png&fullPage=true" \
    -H "X-API-Key: $SNAPRENDER_KEY" \
    -o "screenshots/${safe_name}.png"

  echo "Captured: ${path} -> ${safe_name}.png"
done

Getting JSON Instead of Binary

If you need metadata along with the image (dimensions, file size, cache status), request a JSON response:

curl -s "https://app.snap-render.com/v1/screenshot?url=https://example.com&format=png&response_type=json" \
  -H "X-API-Key: $SNAPRENDER_KEY" | python3 -m json.tool

This returns:

{
  "url": "https://example.com",
  "format": "png",
  "width": 1280,
  "height": 800,
  "image": "data:image/png;base64,iVBOR...",
  "size": 45231,
  "cache": false,
  "responseTime": 2134,
  "remainingCredits": 487
}

The image is base64-encoded in the image field. Extract and decode it:

curl -s "https://app.snap-render.com/v1/screenshot?url=https://example.com&response_type=json" \
  -H "X-API-Key: $SNAPRENDER_KEY" \
  | python3 -c "import sys,json,base64; d=json.load(sys.stdin); open('out.png','wb').write(base64.b64decode(d['image'].split(',')[1]))"

Check Your Usage

Monitor how many screenshots you have left this month:

curl -s "https://app.snap-render.com/v1/screenshot/info?action=usage" \
  -H "X-API-Key: $SNAPRENDER_KEY" | python3 -m json.tool

Error Handling in Scripts

The API returns JSON error responses with HTTP status codes. Check them in your scripts:

response=$(curl -s -w "\n%{http_code}" \
  "https://app.snap-render.com/v1/screenshot?url=https://example.com" \
  -H "X-API-Key: $SNAPRENDER_KEY")

http_code=$(echo "$response" | tail -1)
body=$(echo "$response" | sed '$d')

if [ "$http_code" -eq 200 ]; then
  echo "$body" > screenshot.png
  echo "Success"
elif [ "$http_code" -eq 429 ]; then
  echo "Rate limited or quota exceeded"
elif [ "$http_code" -eq 401 ]; then
  echo "Invalid API key"
else
  echo "Error $http_code: $body"
fi

Common Parameters Reference

Parameter Values Default Description
url Any URL required Target website
format png, jpeg, webp, pdf png Output format
width 320-3840 1280 Viewport width (px)
height 200-10000 800 Viewport height (px)
fullPage true/false false Capture full scrollable page
quality 1-100 90 JPEG/WebP quality
darkMode true/false false Dark color scheme
device iphone_14, iphone_15_pro, pixel_7, ipad_pro, macbook_pro none Device preset
blockAds true/false true Block ads
blockCookieBanners true/false true Remove cookie banners
hideSelectors CSS selectors none Elements to hide
delay 0-10000 0 Wait ms after page load
cache true/false false Use cached result
response_type json binary Response format

Summary

cURL and a screenshot API give you automated website captures without writing application code. This works for one-off captures, batch processing, cron jobs, and CI/CD pipelines.

Get a free API key (500 screenshots/month, no credit card) and start capturing in under a minute.

Try SnapRender Free

500 free screenshots/month, no credit card required.

Sign up free