Capture a website screenshot
curl --request POST \
--url https://www.ntanduy.com/api/v1/screenshot \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"url": "https://example.com",
"width": 1280,
"height": 720,
"fullPage": false,
"device": "desktop",
"theme": "light",
"delay": 0,
"refreshCache": false
}
'import requests
url = "https://www.ntanduy.com/api/v1/screenshot"
payload = {
"url": "https://example.com",
"width": 1280,
"height": 720,
"fullPage": False,
"device": "desktop",
"theme": "light",
"delay": 0,
"refreshCache": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
url: 'https://example.com',
width: 1280,
height: 720,
fullPage: false,
device: 'desktop',
theme: 'light',
delay: 0,
refreshCache: false
})
};
fetch('https://www.ntanduy.com/api/v1/screenshot', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://www.ntanduy.com/api/v1/screenshot",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'url' => 'https://example.com',
'width' => 1280,
'height' => 720,
'fullPage' => false,
'device' => 'desktop',
'theme' => 'light',
'delay' => 0,
'refreshCache' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://www.ntanduy.com/api/v1/screenshot"
payload := strings.NewReader("{\n \"url\": \"https://example.com\",\n \"width\": 1280,\n \"height\": 720,\n \"fullPage\": false,\n \"device\": \"desktop\",\n \"theme\": \"light\",\n \"delay\": 0,\n \"refreshCache\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://www.ntanduy.com/api/v1/screenshot")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"url\": \"https://example.com\",\n \"width\": 1280,\n \"height\": 720,\n \"fullPage\": false,\n \"device\": \"desktop\",\n \"theme\": \"light\",\n \"delay\": 0,\n \"refreshCache\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.ntanduy.com/api/v1/screenshot")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"url\": \"https://example.com\",\n \"width\": 1280,\n \"height\": 720,\n \"fullPage\": false,\n \"device\": \"desktop\",\n \"theme\": \"light\",\n \"delay\": 0,\n \"refreshCache\": false\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"cached": true,
"dataUrl": "<string>",
"width": 123,
"height": 123
}
}Screenshot tools
Capture a website screenshot
Capture a public webpage as a PNG using a scoped API key.
POST
/
api
/
v1
/
screenshot
Capture a website screenshot
curl --request POST \
--url https://www.ntanduy.com/api/v1/screenshot \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"url": "https://example.com",
"width": 1280,
"height": 720,
"fullPage": false,
"device": "desktop",
"theme": "light",
"delay": 0,
"refreshCache": false
}
'import requests
url = "https://www.ntanduy.com/api/v1/screenshot"
payload = {
"url": "https://example.com",
"width": 1280,
"height": 720,
"fullPage": False,
"device": "desktop",
"theme": "light",
"delay": 0,
"refreshCache": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
url: 'https://example.com',
width: 1280,
height: 720,
fullPage: false,
device: 'desktop',
theme: 'light',
delay: 0,
refreshCache: false
})
};
fetch('https://www.ntanduy.com/api/v1/screenshot', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://www.ntanduy.com/api/v1/screenshot",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'url' => 'https://example.com',
'width' => 1280,
'height' => 720,
'fullPage' => false,
'device' => 'desktop',
'theme' => 'light',
'delay' => 0,
'refreshCache' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://www.ntanduy.com/api/v1/screenshot"
payload := strings.NewReader("{\n \"url\": \"https://example.com\",\n \"width\": 1280,\n \"height\": 720,\n \"fullPage\": false,\n \"device\": \"desktop\",\n \"theme\": \"light\",\n \"delay\": 0,\n \"refreshCache\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://www.ntanduy.com/api/v1/screenshot")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"url\": \"https://example.com\",\n \"width\": 1280,\n \"height\": 720,\n \"fullPage\": false,\n \"device\": \"desktop\",\n \"theme\": \"light\",\n \"delay\": 0,\n \"refreshCache\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.ntanduy.com/api/v1/screenshot")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"url\": \"https://example.com\",\n \"width\": 1280,\n \"height\": 720,\n \"fullPage\": false,\n \"device\": \"desktop\",\n \"theme\": \"light\",\n \"delay\": 0,\n \"refreshCache\": false\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"cached": true,
"dataUrl": "<string>",
"width": 123,
"height": 123
}
}For server-to-server use, send a Pirehub API key with the
screenshot:capture
scope in x-pirehub-api-key or as a bearer token. See
Authentication for credential handling.
See the Website screenshots guide for capture options,
examples, caching, and limits.
The response contains data.dataUrl (a PNG data URI), the actual image width
and height, and a cached flag. Use refreshCache: true to request a fresh
capture. Cache hits remain subject to the API key’s limits.
This scope grants access to POST /api/v1/screenshot only.Authorizations
pirehubOAuthpirehubApiKeybearerApiKeyrecaptchaToken
OAuth 2.0 Authorization Code with PKCE, issued by Pirehub's Clerk authorization server. Request only the scopes required by the operation.
Body
application/json
Public HTTP(S) URL without credentials; only ports 80 and 443 are allowed.
Maximum string length:
2048Required range:
300 <= x <= 1920Required range:
168 <= x <= 4096Capture the full page instead of only the viewport.
Available options:
desktop, mobile Available options:
light, dark Additional capture delay in milliseconds.
Available options:
0, 2000, 5000 Bypass the cached screenshot.