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.