API Screenshot Sito Web#
L'endpoint POST /v1/convert/website-to-screenshot scopre ogni pagina di un sito web (tramite parsing della sitemap o un crawl completo in ampiezza, breadth-first), cattura uno screenshot PNG a pagina intera di ciascuna pagina e raggruppa i risultati in un unico archivio ZIP. I job vengono sempre eseguiti in modo asincrono: l'API restituisce immediatamente HTTP 202 con un batch_id, il completamento viene segnalato tramite polling dello stato del batch, un callback webhook o una notifica email, e la risposta dello stato del batch include un URL di download presigned per lo ZIP finito. Richiede un piano a pagamento e una chiave API privata.
Endpoint#
POST /v1/convert/website-to-screenshot
Content-Type: application/json
Formato di output: archivio ZIP contenente uno screenshot PNG per ogni pagina scoperta.
Modalità: sempre asincrona. Restituisce immediatamente HTTP 202.
Autenticazione#
Questo endpoint richiede una chiave API privata. Le chiavi pubbliche non sono supportate per la cattura di siti web.
X-API-Key: sk_your_private_key
Parametri della richiesta#
Parametri di scoperta del sito web#
| Parametro | Tipo | Obbligatorio | Predefinito | Descrizione | Limitazioni per piano |
|---|---|---|---|---|---|
url |
string |
Sì | -- | L'URL base del sito web (es. https://example.com). Usato come radice per la scoperta delle pagine. |
-- |
crawl_mode |
string |
No | "auto" |
Metodo di scoperta degli URL. Uno tra "auto", "sitemap" o "full". Vedi Modalità di crawl qui sotto. |
Sitemap richiede Indie+, Full richiede Studio+ |
include_patterns |
string[] |
No | null |
Pattern regex per inserire in whitelist gli URL scoperti. Usato solo in modalità di crawl full. |
-- |
exclude_patterns |
string[] |
No | Valori predefiniti di sistema | Pattern regex per inserire in blacklist gli URL. Usato solo in modalità di crawl full. Se omesso, usa i valori predefiniti integrati che escludono asset statici, pagine di login/admin/carrello e paginazione profonda. |
-- |
Parametri di notifica#
| Parametro | Tipo | Obbligatorio | Predefinito | Descrizione | Limitazioni per piano |
|---|---|---|---|---|---|
output_filename |
string |
No | Generato automaticamente | Nome base personalizzato per il file ZIP di output. Il timestamp viene aggiunto automaticamente. | -- |
notification_email |
string |
No | Email del proprietario del progetto | Indirizzo email da notificare al completamento del job. | -- |
callback_url |
string |
No | -- | URL webhook che riceve una richiesta POST al completamento. | Richiede accesso webhook |
Parametri del browser e del rendering#
Queste impostazioni si applicano alla cattura di ogni singola pagina all'interno del sito web.
| Parametro | Tipo | Obbligatorio | Predefinito | Descrizione | Limitazioni per piano |
|---|---|---|---|---|---|
viewport_width |
integer |
No | 1920 |
Larghezza del viewport del browser in pixel. La larghezza dello screenshot corrisponde a questo valore. | -- |
viewport_height |
integer |
No | 1080 |
Altezza del viewport del browser in pixel. Usata come riferimento per il rendering e il calcolo delle unità viewport. | -- |
load_media |
boolean |
No | true |
Attende il caricamento completo di tutte le immagini e i video prima della cattura. | -- |
enable_scroll |
boolean |
No | true |
Scorre ogni pagina per attivare i contenuti a caricamento lazy. | -- |
handle_sticky_header |
boolean |
No | true |
Rileva header sticky/fissi e li gestisce prima della cattura. | -- |
handle_cookies |
boolean |
No | true |
Chiude automaticamente i banner di consenso cookie. | -- |
wait_for_images |
boolean |
No | true |
Attende il completamento del caricamento di tutti gli elementi <img>. |
-- |
wait_for_selector |
string |
No | null |
Selettore CSS da attendere prima della cattura, applicato a ogni pagina. Restituisce 422 se non compare mai entro wait_for_selector_timeout. Utile per le SPA che idratano il contenuto dopo il caricamento. |
-- |
wait_for_selector_timeout |
integer |
No | 10000 |
Millisecondi di attesa per wait_for_selector (massimo 60000). |
-- |
block_ads |
boolean |
No | false |
Interrompe le richieste ai domini noti di pubblicità/tracker in modo che non vengano mai caricati, renderizzati o rallentino la cattura. | -- |
block_media |
boolean |
No | false |
Interrompe completamente le richieste di immagini e audio/video per un rendering più veloce e leggero. A differenza di load_media (che controlla solo l'attesa), questo impedisce del tutto il download dei media. |
-- |
Autenticazione e richieste personalizzate#
| Parametro | Tipo | Obbligatorio | Predefinito | Descrizione | Limitazioni per piano |
|---|---|---|---|---|---|
auth |
object |
No | null |
Credenziali HTTP Basic Auth applicate a ogni pagina. Formato: {"username": "...", "password": "..."}. |
Richiede accesso basic auth |
cookies |
array |
No | null |
Array di oggetti cookie iniettati prima di ogni caricamento di pagina. Massimo 50 cookie. | Richiede accesso basic auth |
headers |
object |
No | null |
Header HTTP personalizzati inviati con ogni richiesta. Massimo 20 header. | Richiede accesso basic auth |
single_page e pdf_options non sono applicabili agli screenshot. Ogni pagina viene sempre catturata come una singola immagine PNG a pagina intera.
Modalità di crawl#
"auto" (predefinito)#
Usa la modalità di crawl più alta consentita dal tuo piano. Se il tuo piano supporta il crawl completo, esegue un crawl completo. Se il tuo piano supporta solo la sitemap, esegue la scoperta tramite sitemap.
"sitemap"#
Scopre le pagine analizzando il sitemap.xml del sito web:
- Recupera
{base_url}/sitemap.xml(timeout di 30 secondi) - Se l'elemento radice è
<sitemapindex>, recupera ricorsivamente ogni sitemap figlia - Estrae tutte le voci
<url><loc>dagli elementi<urlset> - Restituisce l'elenco completo degli URL scoperti
Restituisce un errore se la sitemap è mancante, restituisce uno stato diverso da 200, contiene XML non valido o non ha URL.
"full"#
Esegue un crawl completo in due fasi:
Fase 1 -- Scoperta dei seed:
- Analizza
robots.txtper direttive sitemap e regole di crawl - Controlla i percorsi standard delle sitemap (
/sitemap.xml,/wp-sitemap.xml,/sitemap_index.xml, ecc.) - Scopre i feed RSS/Atom dai tag
<link>e dai percorsi feed comuni - Estrae gli URL seed da tutte le fonti scoperte
Fase 2 -- Crawl dei link in ampiezza (breadth-first):
- Parte dall'URL base più tutti gli URL seed
- Visita ogni pagina e accoda i link dello stesso dominio
- Applica
include_patternseexclude_patternsper filtrare i link - Rispetta le regole di
robots.txt - Rileva ed evita trappole di URL infinite (pagine calendario, filtri sfaccettati, ecc.)
- Deduplica gli URL normalizzando schema, host, parametri di query e rimuovendo i parametri di tracciamento (
utm_*,fbclid,gclid, ecc.)
Pattern di esclusione predefiniti (quando exclude_patterns non viene fornito):
- Asset statici:
*.pdf,*.zip,*.jpg,*.png,*.gif,*.svg,*.css,*.js,*.xml,*.json,*.mp4,*.webm,*.woff,*.woff2 - Percorsi protetti:
/login,/admin,/cart,/checkout - Paginazione profonda: URL con parametri
page=che superano 3 cifre
Risposta#
202 Accepted (immediato)#
{
"status": "processing",
"batch_id": "550e8400-e29b-41d4-a716-446655440000",
"url_count": 42,
"total_discovered": 42,
"discovery_method": "sitemap",
"output_format": "zip"
}
| Campo | Descrizione |
|---|---|
batch_id |
UUID per tracciare il job tramite polling dello stato del batch o webhook. |
url_count |
Numero di pagine che verranno catturate. |
total_discovered |
Numero totale di pagine scoperte dal crawl. |
discovery_method |
"sitemap" o "full_crawl" a seconda della modalità di crawl effettiva. |
Polling dello stato del batch#
Esegui il polling con il batch_id restituito dalla risposta 202:
GET /v1/convert/batch/{batch_id}
X-API-Key: sk_your_private_key
Restituisce lo stato aggregato, gli stati per singolo URL e un URL di download presigned per lo ZIP al completamento. Vedi Polling dello stato del batch per lo schema completo della risposta.
Payload del callback webhook#
Quando viene fornito callback_url, EnConvert invia una richiesta POST al completamento:
{
"job_id": "batch-uuid",
"status": "success",
"batch_id": "550e8400-e29b-41d4-a716-446655440000",
"gcs_uri": "env/files/{project_id}/url-to-screenshot/website_20260405_123456789.zip",
"filename": "website_20260405_123456789.zip",
"file_size": 12345678,
"total_tasks": 42,
"successful_tasks": 40,
"failed_tasks": 2,
"tasks": [
{"url": "https://example.com/", "status": "success", "filename": "example_20260405_001.png"},
{"url": "https://example.com/about", "status": "success", "filename": "example_20260405_002.png"},
{"url": "https://example.com/broken", "status": "failed", "error": "Timeout"}
]
}
Notifica email#
Un'email di completamento viene inviata a notification_email (o all'email del proprietario del progetto per impostazione predefinita) al termine del job, indipendentemente da successo o fallimento.
Limitazioni per piano di abbonamento#
| Funzionalità | Founding | Indie | Studio | Enterprise |
|---|---|---|---|---|
| Cattura sito web | No | Sì | Sì | Sì |
| Modalità di crawl sitemap | No | Sì | Sì | Sì |
| Modalità di crawl full | No | No | Sì | Sì |
| Callback webhook | No | No | Sì | Sì |
| HTTP Basic Auth | No | Sì | Sì | Sì |
| Iniezione cookie | No | Sì | Sì | Sì |
| Header personalizzati | No | Sì | Sì | Sì |
| Limite dimensione batch | 0 | In base al piano | In base al piano | Illimitato |
| Conversioni mensili | 100 | In base al piano | In base al piano | Illimitato |
403 Forbidden.
Esempi di codice#
Python (chiave privata)#
import requests
import time
# Start the website capture
response = requests.post(
"https://api.enconvert.com/v1/convert/website-to-screenshot",
headers={"X-API-Key": "sk_your_private_key"},
json={
"url": "https://example.com",
"crawl_mode": "sitemap",
"output_filename": "example-screenshots",
"viewport_width": 1440,
"viewport_height": 900
}
)
data = response.json()
print(f"Batch ID: {data['batch_id']}")
print(f"Pages found: {data['url_count']}")
# Poll for completion
batch_id = data["batch_id"]
while True:
status = requests.get(
f"https://api.enconvert.com/v1/convert/batch/{batch_id}",
headers={"X-API-Key": "sk_your_private_key"}
).json()
print(f"Status: {status['status']} ({status['completed']}/{status['total']})")
if status["status"] in ("completed", "partial", "failed"):
if status.get("zip_download_url"):
print(f"Download: {status['zip_download_url']}")
break
time.sleep(5)
PHP (chiave privata)#
$ch = curl_init("https://api.enconvert.com/v1/convert/website-to-screenshot");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: sk_your_private_key"
],
CURLOPT_POSTFIELDS => json_encode([
"url" => "https://example.com",
"crawl_mode" => "sitemap",
"output_filename" => "example-screenshots",
"viewport_width" => 1440,
"viewport_height" => 900
])
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
echo "Batch ID: " . $response["batch_id"] . "\n";
echo "Pages found: " . $response["url_count"] . "\n";
Node.js (chiave privata)#
const response = await fetch("https://api.enconvert.com/v1/convert/website-to-screenshot", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "sk_your_private_key"
},
body: JSON.stringify({
url: "https://example.com",
crawl_mode: "sitemap",
output_filename: "example-screenshots",
viewport_width: 1440,
viewport_height: 900
})
});
const data = await response.json();
console.log(`Batch ID: ${data.batch_id}`);
console.log(`Pages found: ${data.url_count}`);
// Poll for completion
const poll = async () => {
const status = await fetch(
`https://api.enconvert.com/v1/convert/batch/${data.batch_id}`,
{ headers: { "X-API-Key": "sk_your_private_key" } }
).then(r => r.json());
console.log(`Status: ${status.status} (${status.completed}/${status.total})`);
if (["completed", "partial", "failed"].includes(status.status)) {
if (status.zip_download_url) console.log(`Download: ${status.zip_download_url}`);
return;
}
setTimeout(poll, 5000);
};
poll();
Go (chiave privata)#
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
body, _ := json.Marshal(map[string]interface{}{
"url": "https://example.com",
"crawl_mode": "sitemap",
"output_filename": "example-screenshots",
"viewport_width": 1440,
"viewport_height": 900,
})
req, _ := http.NewRequest("POST", "https://api.enconvert.com/v1/convert/website-to-screenshot", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", "sk_your_private_key")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
respBody, _ := io.ReadAll(resp.Body)
fmt.Println(string(respBody))
}
Con callback webhook#
{
"url": "https://example.com",
"crawl_mode": "full",
"callback_url": "https://your-server.com/webhook/enconvert",
"output_filename": "example-full-site-screenshots",
"include_patterns": [".*\\/blog\\/.*", ".*\\/docs\\/.*"]
}
Con autenticazione (sito protetto da password)#
{
"url": "https://staging.example.com",
"crawl_mode": "sitemap",
"auth": {
"username": "admin",
"password": "staging-password"
},
"cookies": [
{"name": "session_token", "value": "abc123", "domain": "staging.example.com"}
]
}
Risposte di errore#
| Stato | Condizione |
|---|---|
400 Bad Request |
Parametro url mancante o vuoto |
400 Bad Request |
Nessun URL trovato nella sitemap |
400 Bad Request |
Timeout durante il recupero della sitemap (limite di 30 secondi) |
400 Bad Request |
Risposta diversa da 200 dall'URL della sitemap |
400 Bad Request |
XML non valido nella sitemap |
400 Bad Request |
Formato sitemap non riconosciuto |
400 Bad Request |
Nessuna pagina scoperta (il crawl completo ha trovato zero URL) |
400 Bad Request |
Struttura di auth, cookies o headers non valida |
402 Payment Required |
Quota mensile di ops superata dal numero di pagine scoperte |
402 Payment Required |
Limite di storage raggiunto |
403 Forbidden |
Crawling del sito web non disponibile sul piano attuale (piano Founding) |
403 Forbidden |
La modalità di crawl full richiede il piano Studio o superiore |
403 Forbidden |
Il numero di pagine scoperte supera il limite di dimensione del batch |
403 Forbidden |
Funzionalità non disponibile sul piano (webhook, basic auth) |
500 Internal Server Error |
Errore di crawl o cattura |
Limiti#
| Limite | Valore |
|---|---|
| Timeout di recupero sitemap | 30 secondi |
| Timeout globale del crawl (modalità full) | 10 minuti |
| Profondità massima del crawl (modalità full) | 10 livelli |
| Timeout di crawl per pagina (modalità full) | 30 secondi |
| Limite di memoria del crawler | 512 MB |
| Soglia trappola infinita | 20 URL per pattern di URL |
| Timeout di recupero robots.txt | 10 secondi |
| Pagine massime per crawl | Limite di dimensione batch del piano |
| Cookie massimi per richiesta | 50 |
| Header personalizzati massimi per richiesta | 20 |
| Timeout di consegna webhook | 30 secondi |
| Conversioni mensili | Dipende dal piano |
| Conservazione dei file | Dipende dal piano |
Domande frequenti#
Come faccio a fare lo screenshot di ogni pagina di un sito web con un'API?#
Invia una richiesta POST a /v1/convert/website-to-screenshot con l'url base del sito e la tua chiave privata nell'header X-API-Key. L'API scopre ogni pagina (sitemap o crawl completo), cattura un PNG a pagina intera per ciascuna, le raggruppa in un archivio ZIP e restituisce HTTP 202 con un batch_id di cui puoi fare polling per ottenere il link di download.
Posso controllare la dimensione o il formato degli screenshot?#
La larghezza dello screenshot corrisponde a viewport_width (predefinito 1920), e viewport_height viene usato come riferimento per il rendering. Ogni pagina viene sempre catturata come un singolo PNG a pagina intera. I parametri single_page e pdf_options non si applicano agli screenshot.
Come scarico gli screenshot quando il job si completa?#
Esegui il polling di GET /v1/convert/batch/{batch_id} con la tua chiave privata per ottenere lo stato aggregato, gli stati per singolo URL e un URL di download ZIP presigned, oppure passa un callback_url per ricevere un POST webhook al completamento. Un'email di completamento viene anche inviata a notification_email (o al proprietario del progetto per impostazione predefinita).
Posso fare lo screenshot di un sito protetto da password o di staging?#
Sì, sui piani con accesso basic auth: passa auth con username e password per l'HTTP Basic Auth applicata a ogni pagina, inietta fino a 50 cookies di sessione, oppure invia fino a 20 headers personalizzati.
Perché l'endpoint website to screenshot restituisce 403 Forbidden?#
Le cause più comuni: la cattura di siti web non è disponibile sul piano Founding, crawl_mode: "full" richiede Studio o superiore, il numero di pagine scoperte supera il limite di dimensione batch del tuo piano, oppure una funzionalità richiesta (webhook, basic auth) non è inclusa nel tuo piano.