Getting started
The Snapshot Archive API gives you programmatic control over website screenshot capture, monitoring, and visual change detection. Instead of using the dashboard manually, you can automate everything — create monitors, trigger captures, download screenshots, and receive webhook notifications when pages change.
API access is available on Starter plans and above. You interact with the API over HTTPS using standard REST conventions: JSON request bodies, Bearer token authentication, and predictable HTTP status codes.
https://api.snapshotarchive.com/v1Quick start: your first screenshot in 4 steps
This walkthrough takes you from zero to a downloaded screenshot. Each step builds on the previous one — the IDs you need always come from the response of the step before.
1. Get your API key
Go to Dashboard → API Keys and create a new key. Copy the key immediately — for security reasons, the full key is only shown once. You'll include it in every API request as a Bearer token.
2. Create a monitor
A monitor tells Snapshot Archive which URL to capture and how often. When you create one, the API returns the monitor object with its id — you'll use this ID to trigger captures and retrieve snapshots.
curl -X POST https://api.snapshotarchive.com/v1/monitors \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"url": "https://example.com",
"frequency_minutes": 720,
"device_type": "desktop",
"viewport_width": 1920,
"viewport_height": 1080
}'$response = Http::withToken('YOUR_API_KEY')
->post('https://api.snapshotarchive.com/v1/monitors', [
'url' => 'https://example.com',
'frequency_minutes' => 720,
'device_type' => 'desktop',
'viewport_width' => 1920,
'viewport_height' => 1080,
]);
$monitor = $response->json('data');import requests
resp = requests.post('https://api.snapshotarchive.com/v1/monitors',
headers={'Authorization': 'Bearer YOUR_API_KEY', 'Accept': 'application/json'},
json={'url': 'https://example.com', 'frequency_minutes': 720,
'device_type': 'desktop', 'viewport_width': 1920, 'viewport_height': 1080})
monitor = resp.json()['data']const resp = await fetch('https://api.snapshotarchive.com/v1/monitors', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json', 'Accept': 'application/json' },
body: JSON.stringify({ url: 'https://example.com', frequency_minutes: 720,
device_type: 'desktop', viewport_width: 1920, viewport_height: 1080 }),
});
const { data: monitor } = await resp.json();require 'net/http'
require 'json'
uri = URI('https://api.snapshotarchive.com/v1/monitors')
req = Net::HTTP::Post.new(uri, 'Authorization' => "Bearer #{API_KEY}",
'Content-Type' => 'application/json', 'Accept' => 'application/json')
req.body = { url: 'https://example.com', frequency_minutes: 720,
device_type: 'desktop', viewport_width: 1920, viewport_height: 1080 }.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
monitor = JSON.parse(resp.body)['data']body := strings.NewReader(`{"url":"https://example.com","frequency_minutes":720,
"device_type":"desktop","viewport_width":1920,"viewport_height":1080}`)
req, _ := http.NewRequest("POST", "https://api.snapshotarchive.com/v1/monitors", body)
req.Header.Set("Authorization", "Bearer "+apiKey)
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)3. Trigger a snapshot
Creating a monitor sets up the schedule, but you can also trigger a capture right away. The API returns 202 Accepted with a snapshot_id — the capture happens asynchronously in the background and typically finishes within 10–30 seconds.
# Use the monitor ID returned from step 2 (e.g. 42)
curl -X POST https://api.snapshotarchive.com/v1/monitors/42/trigger \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
# Response: {"data": {"message": "Snapshot queued successfully.", "snapshot_id": "9e8f7a6b-..."}}
$response = Http::withToken('YOUR_API_KEY')
->post('https://api.snapshotarchive.com/v1/monitors/42/trigger');
$snapshot = $response->json('data'); // snapshot_id: "9e8f7a6b-..."resp = requests.post(f'{BASE}/monitors/42/trigger', headers=headers)
snapshot = resp.json()['data'] # snapshot_id: "9e8f7a6b-..."const { data } = await fetch(`${BASE}/monitors/42/trigger`, {
method: 'POST', headers,
}).then(r => r.json()); // snapshot_id: "9e8f7a6b-..."uri = URI("#{BASE}/monitors/42/trigger")
req = Net::HTTP::Post.new(uri, headers)
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
snapshot = JSON.parse(resp.body)['data']req, _ := http.NewRequest("POST", BASE+"/monitors/42/trigger", nil)
req.Header.Set("Authorization", "Bearer "+apiKey)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()4. Get the result
Poll the snapshot endpoint using the snapshot_id from step 3. Once the status field changes from pending to completed, you can download the screenshot image, PDF, or HTML source.
# Poll until status is "completed" or "failed"
curl https://api.snapshotarchive.com/v1/snapshots/9e8f7a6b-... \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
# Once completed, download the screenshot
curl -L https://api.snapshotarchive.com/v1/snapshots/9e8f7a6b-.../screenshot \
-H "Authorization: Bearer YOUR_API_KEY" \
-o screenshot.png// Poll until status is "completed" or "failed"
$response = Http::withToken('YOUR_API_KEY')
->get('https://api.snapshotarchive.com/v1/snapshots/9e8f7a6b-...');
$snapshot = $response->json('data');
// Once completed, download the screenshot
$image = Http::withToken('YOUR_API_KEY')
->get('https://api.snapshotarchive.com/v1/snapshots/9e8f7a6b-.../screenshot');
file_put_contents('screenshot.png', $image->body());# Poll until status is "completed" or "failed"
resp = requests.get(f'{BASE}/snapshots/9e8f7a6b-...', headers=headers)
snapshot = resp.json()['data']
# Once completed, download the screenshot
img = requests.get(f'{BASE}/snapshots/9e8f7a6b-.../screenshot', headers=headers)
with open('screenshot.png', 'wb') as f:
f.write(img.content)// Poll until status is "completed" or "failed"
const { data: snapshot } = await fetch(`${BASE}/snapshots/9e8f7a6b-...`, { headers })
.then(r => r.json());
// Once completed, download the screenshot
const img = await fetch(`${BASE}/snapshots/9e8f7a6b-.../screenshot`, { headers });
const fs = await import('fs');
fs.writeFileSync('screenshot.png', Buffer.from(await img.arrayBuffer()));# Poll until status is "completed" or "failed"
uri = URI("#{BASE}/snapshots/9e8f7a6b-...")
req = Net::HTTP::Get.new(uri, headers)
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
snapshot = JSON.parse(resp.body)['data']
# Once completed, download the screenshot
uri = URI("#{BASE}/snapshots/9e8f7a6b-.../screenshot")
req = Net::HTTP::Get.new(uri, headers)
img = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |h| h.request(req) }
File.binwrite('screenshot.png', img.body)// Poll until status is "completed" or "failed"
req, _ := http.NewRequest("GET", BASE+"/snapshots/9e8f7a6b-...", nil)
req.Header.Set("Authorization", "Bearer "+apiKey)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
// Once completed, download the screenshot
req2, _ := http.NewRequest("GET", BASE+"/snapshots/9e8f7a6b-.../screenshot", nil)
req2.Header.Set("Authorization", "Bearer "+apiKey)
resp2, _ := http.DefaultClient.Do(req2)
defer resp2.Body.Close()
out, _ := os.Create("screenshot.png")
io.Copy(out, resp2.Body)- Monitor ID — returned when you create a monitor or list monitors (
data.id) - Snapshot UUID — returned when you trigger a snapshot (
data.snapshot_id) or list snapshots - Project ID — returned when you create or list projects
- Diff ID — returned when you list diffs for a monitor
GET /v1/monitors to get their IDs programmatically.