Five ways, from "I need it once" to "I need 10,000 a day". Each has trade-offs. Pick the one that matches what you're actually doing.
Updated January 2026.
If you have curl and an internet connection, you can do this right now:
curl "https://api.sitetrace.it.com/api/shot?url=https://example.com" --output shot.png
That's it. The image lands in shot.png. You can open it, attach it to an email, post it on Slack — whatever you need.
This uses our free, no-signup tier. 100 calls/day per IP. Good for "I need to take a screenshot once in a while" and "I want to test what an API can do before I commit".
Trade-off: Goes through our servers, so don't use it for sensitive URLs.
Sign up at /signup to get a free key (1,000 calls/day). Then:
curl "https://api.sitetrace.it.com/api/shot?url=https://example.com" \
-H "Authorization: Bearer stk_your_key_here" \
--output shot.png
Same call, higher quota. If you're doing this 50 times a day, the free tier without a key runs out; this is what you switch to.
If you have node and npm:
npm install puppeteer
node -e "
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 720 });
await page.goto('https://example.com', { waitUntil: 'networkidle0' });
await page.screenshot({ path: 'shot.png' });
await browser.close();
})();
"
You get the full power of headless Chrome: any viewport, full-page capture, dark mode emulation, executing JS before the shot, etc.
Trade-off: Requires ~300 MB of Chrome download, plus the runtime cost of keeping a browser around. Doesn't scale to "screenshot 10,000 URLs in an hour" without infrastructure work.
Modern Chrome supports a --screenshot flag:
google-chrome --headless --disable-gpu --screenshot=shot.png --window-size=1280,720 https://example.com
(On Windows, it's "C:\Program Files\Google\Chrome\Application\chrome.exe" with the same flags. Or use Edge.)
Only captures the viewport, not the full page. No JS hooks, no waiting, no dark mode. But it works with the Chrome you already have, no install.
If you're doing this at scale — link previews for a chat app, OG images for a newsletter tool, screenshots for a marketplace listing — the right answer is an API:
async function getShot(url) {
const r = await fetch('https://api.sitetrace.it.com/api/shot?url=' + encodeURIComponent(url), {
headers: { 'Authorization': 'Bearer ' + API_KEY }
});
return Buffer.from(await r.arrayBuffer());
}
No Chrome to install, no memory leaks to debug, no bot-detection arms race. The API runs in the vendor's cloud; you just call it. The cost is real (~$0.01–0.05 per shot at scale) but the ops savings are larger.
Our full comparison of screenshot APIs is in the best screenshot APIs 2026 guide.
| Situation | Use this |
|---|---|
| One-off, no install, right now | Option 1 (curl + no-signup API) |
| Few per day, want a free quota | Option 2 (curl + free key) |
| Local script, want control, low volume | Option 3 (Puppeteer) |
| One screenshot, want the actual installed Chrome | Option 4 (chrome --screenshot) |
| 1000+ per day, want someone else to deal with it | Option 5 (screenshot API) |