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

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 true 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