R2 Storage
Instead of receiving the screenshot as binary data, you can upload it directly to your Cloudflare R2 bucket. The API returns a JSON response with the public URL of the uploaded file.
Setup
- Create a Cloudflare R2 bucket in your Cloudflare dashboard
- Generate an R2 API token with read/write permissions for the bucket
- Go to Storage Settings in the ShotOne dashboard
- Click Add Credential and enter your R2 details:
- Account ID — Your Cloudflare account ID
- Access Key ID — From your R2 API token
- Secret Access Key — From your R2 API token
- Bucket Name — Your R2 bucket name
- Public URL — Your bucket's public domain (optional, for custom URLs)
- Click Test Connection to verify it works
Your credentials are encrypted with AES-256-GCM before storage. Only the ShotOne API can decrypt them to upload screenshots.
Self-hosting note: If you run your own gateway instance, R2 storage requires
DASHBOARD_INTERNAL_URLandINTERNAL_API_KEYto be configured in the gateway environment so it can fetch your encrypted R2 credentials from the dashboard API.
Usage
Add storage: "r2" to your request. If you have multiple R2 credentials, specify which one to use with r2CredentialId.
Using Default Credential
curl -X POST "https://api.shotone.io/screenshot" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"storage": "r2"
}' Using a Specific Credential
curl -X POST "https://api.shotone.io/screenshot" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"format": "webp",
"quality": 90,
"storage": "r2",
"r2CredentialId": "clxxx..."
}' Response
When storage: "r2" is set, the response is JSON instead of binary:
{
"success": true,
"storage": "r2",
"url": "https://your-bucket.r2.dev/screenshots/20250130-143022-a1b2c3d4.webp",
"bucket": "your-bucket",
"key": "screenshots/20250130-143022-a1b2c3d4.webp"
} | Field | Type | Description |
|---|---|---|
success | boolean | Always true on success |
storage | string | Always "r2" |
url | string | Public URL to access the screenshot |
bucket | string | R2 bucket name |
key | string | Object key in the bucket |
Code Examples
Node.js
const response = await fetch('https://api.shotone.io/screenshot', {
method: 'POST',
headers: {
'X-API-Key': process.env.SHOTONE_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: 'https://example.com',
storage: 'r2',
r2CredentialId: 'clxxx...',
}),
});
const data = await response.json();
console.log(data.url); // Public URL of the screenshot Python
import requests
import os
response = requests.post(
'https://api.shotone.io/screenshot',
headers={
'X-API-Key': os.environ['SHOTONE_API_KEY'],
'Content-Type': 'application/json',
},
json={
'url': 'https://example.com',
'storage': 'r2',
'r2CredentialId': 'clxxx...',
},
)
data = response.json()
print(data['url']) # Public URL of the screenshot File Naming
Screenshots are stored with auto-generated keys in the format:
screenshots/{YYYYMMDD-HHMMSS}-{random-hex}.{format}
For example: screenshots/20250130-143022-a1b2c3d4e5f6g7h8.png
Errors
| Status | Error | Cause |
|---|---|---|
400 | R2 storage is not configured on this gateway | R2 support is not enabled on the server |
400 | failed to get R2 credentials | Credential not found, not active, or doesn't belong to the user |
502 | failed to upload to R2 | Upload to R2 failed (check credentials and bucket permissions) |