API Screenshot Sito Web#

L'endpoint POST /v1/convert/url-to-screenshot cattura uno screenshot a pagina intera di qualsiasi URL pubblicamente accessibile come immagine PNG ad alta fedeltà. Gestisce automaticamente banner cookie, modali, contenuti a caricamento lazy, animazioni attivate dallo scroll e header sticky per produrre una cattura pulita e accurata. Eseguilo in modo sincrono per ottenere un URL di download presigned o i byte PNG grezzi, oppure usa la modalità asincrona per catturare più URL in batch.


Endpoint#

POST /v1/convert/url-to-screenshot

Content-Type: application/json

Formato di output: PNG (sempre). Il formato di output non è configurabile. Tutti gli screenshot vengono catturati come immagini PNG a pagina intera.


Autenticazione#

Questo endpoint supporta l'autenticazione sia con chiave privata che con chiave pubblica.

Chiave privata#

Includi la tua chiave segreta nell'header X-API-Key. Usa questo metodo per le chiamate server-to-server in cui la chiave non è mai esposta al client.

X-API-Key: sk_your_private_key

Chiave pubblica con JWT#

Per l'uso lato client, genera prima un token JWT usando la tua chiave pubblica, poi passalo come Bearer token.

Passo 1 -- Ottieni un token:

POST /v1/auth/token
X-API-Key: pk_your_public_key

Passo 2 -- Usa il token:

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Nota: Le richieste con chiave pubblica sono limitate a un singolo URL, alla modalità sincrona e al download diretto. La modalità asincrona, l'elaborazione in batch, i webhook e le email di notifica non sono disponibili con le chiavi pubbliche.

Parametri della richiesta#

Parametri di primo livello#

Parametro Tipo Obbligatorio Predefinito Descrizione Limitazione per piano
url string o string[] -- Una singola stringa URL o un array di URL da catturare. Più URL richiedono la modalità asincrona. --
async_mode boolean No false Esegue la cattura in modo asincrono. Restituisce immediatamente un batch_id. Obbligatorio per il batch (più URL). Richiede accesso asincrono
direct_download boolean No false Restituisce i byte PNG grezzi nel corpo della risposta invece di una risposta JSON con un URL presigned. Forzato a true per le chiavi pubbliche. Incompatibile con async_mode e con più URL. --
output_format boolean No false Quando è true con più URL, raggruppa tutti i PNG di output in un unico archivio ZIP. Richiede più URL. Richiede accesso all'output ZIP
output_filename string No Generato automaticamente Nome file personalizzato per il file di output. L'estensione .png viene aggiunta automaticamente. Formato predefinito: {domain}_{timestamp}.png. --
job_id string No -- ID job fornito dal client per il recupero in caso di timeout. Solo chiavi pubbliche. Quando una conversione sincrona supera i limiti di timeout del reverse proxy, il client può interrogare GET /v1/convert/status/{job_id} per recuperare il risultato. Ignorato per le chiavi private. --
notification_email string No Email del proprietario del progetto Indirizzo email da notificare al completamento di un job asincrono. Solo chiavi private. --
callback_url string No -- URL webhook che riceve una richiesta POST al completamento della cattura. Solo chiavi private. Richiede accesso webhook

Parametri browser e rendering#

Parametro Tipo Obbligatorio Predefinito Descrizione Limitazione 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. L'altezza effettiva dello screenshot è determinata dall'altezza completa del contenuto della pagina. --
load_media boolean No true Attende il caricamento completo di tutte le immagini e i video prima della cattura. Quando è false, la cattura è più veloce ma i contenuti multimediali possono apparire come segnaposto. --
enable_scroll boolean No true Scorre la pagina dall'alto verso il basso per attivare il caricamento dei contenuti lazy (loader basati su IntersectionObserver). --
handle_sticky_header boolean No true Rileva gli header sticky/fixed e scorre in cima alla pagina prima della cattura, così l'header viene renderizzato correttamente in cima allo screenshot. --
handle_cookies boolean No true Chiude automaticamente i banner di consenso cookie (OneTrust, Cookiebot, Didomi, Usercentrics e banner generici). --
wait_for_images boolean No true Attende il completamento del caricamento di tutti gli elementi <img> (timeout di 5 secondi per immagine). --
wait_for_selector string No null Selettore CSS da attendere prima della cattura. 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 Limitazione per piano
auth object No null Credenziali HTTP Basic Auth per l'URL di destinazione. Formato: {"username": "...", "password": "..."}. Non può essere usato insieme a un header Authorization personalizzato. Richiede accesso basic auth
cookies array No null Array di oggetti cookie da iniettare prima della navigazione. Massimo 50 cookie. Ogni cookie deve avere name, value e uno tra domain o url. Richiede accesso basic auth
headers object No null Dizionario di header HTTP personalizzati inviati con ogni richiesta all'URL di destinazione. Massimo 20 header. Header bloccati: host, content-length, transfer-encoding, connection, upgrade, te, trailer. Richiede accesso basic auth
Non supportato: I parametri single_page e pdf_options dell'endpoint url-to-pdf non sono applicabili agli screenshot. Gli screenshot catturano sempre la pagina intera come un'unica immagine continua.

Ogni elemento dell'array cookies deve seguire questa struttura:

Campo Tipo Obbligatorio Predefinito Descrizione
name string -- Nome del cookie.
value string -- Valore del cookie.
domain string Condizionale -- Dominio del cookie. È necessario fornire domain oppure url.
url string Condizionale -- URL a cui associare il cookie. È necessario fornire domain oppure url.
path string No "/" Percorso del cookie. Il valore predefinito è "/" quando è impostato domain.

Risposta#

Sincrona con download diretto (direct_download=true)#

Chiave privata -- restituisce i byte PNG grezzi:

HTTP 200 OK
Content-Type: image/png
Content-Disposition: inline; filename="example_20260405_123456789.png"
X-Object-Key: env/files/{project_id}/url-to-screenshot/example_20260405_123456789.png
X-File-Size: 456789
X-Conversion-Time: 8.2
X-Filename: example_20260405_123456789.png

(binary PNG data)

Chiave pubblica -- restituisce JSON con un URL presigned:

{
    "presigned_url": "https://spaces.example.com/...",
    "object_key": "env/files/{project_id}/url-to-screenshot/example_20260405_123456789.png",
    "filename": "example_20260405_123456789.png",
    "file_size": 456789,
    "conversion_time_seconds": 8.2,
    "job_id": "client-provided-id"
}

Sincrona senza download diretto (direct_download=false)#

Disponibile solo con chiavi private.

{
    "presigned_url": "https://spaces.example.com/...",
    "object_key": "env/files/{project_id}/url-to-screenshot/example_20260405_123456789.png",
    "filename": "example_20260405_123456789.png",
    "file_size": 456789,
    "conversion_time_seconds": 8.2
}

Modalità asincrona#

Restituisce immediatamente un batch_id per il tracciamento.

HTTP 202 Accepted
{
    "status": "processing",
    "batch_id": "550e8400-e29b-41d4-a716-446655440000",
    "url_count": 5,
    "output_format": "individual"
}

Quando output_format=true (raggruppamento ZIP):

{
    "status": "processing",
    "batch_id": "550e8400-e29b-41d4-a716-446655440000",
    "url_count": 5,
    "output_format": "zip"
}

Polling dello stato del job (solo chiavi pubbliche)#

Per il recupero in caso di timeout con chiave pubblica:

GET /v1/convert/status/{job_id}
Authorization: Bearer <jwt_token>
Stato Risposta
In elaborazione {"status": "processing"}
Successo {"status": "success", "presigned_url": "...", "object_key": "..."}
Fallito {"status": "failed", "error": "..."}

Polling dello stato batch (solo chiavi private)#

Per i job batch asincroni, esegui il polling con il batch_id restituito nella 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 gli URL di download presigned. Consulta Polling dello stato batch per lo schema completo della risposta.

Payload del callback webhook#

Quando viene fornito un callback_url, EnConvert invia una richiesta POST a quell'URL al completamento.

Job con URL singolo:

{
    "job_id": "activity_id",
    "status": "success",
    "batch_id": "...",
    "gcs_uri": "object_key",
    "filename": "example_20260405_123456789.png",
    "file_size": 456789
}

Job batch:

{
    "job_id": "activity_id",
    "status": "success",
    "batch_id": "...",
    "total_tasks": 10,
    "successful_tasks": 8,
    "failed_tasks": 2,
    "tasks": [
        {"url": "https://example.com/page1", "status": "success", "filename": "page1.png"},
        {"url": "https://example.com/page2", "status": "failed", "filename": null}
    ]
}

Funzionalità#

Cattura a pagina intera#

Ogni screenshot cattura l'intero contenuto della pagina, non solo il viewport visibile. Il convertitore:

  1. Renderizza la pagina con i valori specificati di viewport_width e viewport_height
  2. Scorre la pagina per attivare tutti i contenuti a caricamento lazy
  3. Calcola l'altezza reale del contenuto usando un DOM tree walker che misura la posizione massima inferiore di tutti gli elementi visibili
  4. Ridimensiona il viewport per includere l'intera altezza del contenuto
  5. Cattura lo screenshot con full_page=true

Il risultato è un'unica immagine PNG allungata dell'intera pagina.

Modalità di cattura pulita#

EnConvert gestisce automaticamente gli ostacoli più comuni delle pagine web per produrre screenshot puliti:

  • Banner di consenso cookie -- Chiude automaticamente i banner di OneTrust, Cookiebot, Didomi, Usercentrics e implementazioni generiche. Opera sia sulla pagina principale che sugli iframe.
  • Chiusura di modali e popup -- Chiude gli overlay usando diverse strategie: tasto Escape, pulsanti di chiusura ARIA, pulsanti di chiusura basati su classe ("Close", "Not now", "No thanks", "Skip"), e pulsanti di dialogo basati su ruolo. Rimuove gli effetti residui di blur, backdrop e inert dopo la chiusura.
  • Rivelazione delle animazioni da scroll -- Forza la visibilità degli elementi nascosti da librerie di animazione attivate dallo scroll, tra cui WOW.js, AOS, ScrollReveal, GSAP ScrollTrigger, e classi di animazione generiche (.fadeIn, .slideIn, ecc.). Rivela anche tutte le slide di Swiper.
  • Pulizia dei dropdown -- Chiude tutti i dropdown aperti, converte gli elementi button di navigazione in veri link anchor per mantenere l'aspetto visivo pulito, nasconde gli elementi role="menu" e riposiziona gli header fixed in posizione static.

Normalizzazione delle unità viewport#

Gli screenshot richiedono una gestione speciale delle unità viewport CSS (vh, svh, lvh, dvh) perché il viewport viene ridimensionato all'altezza completa della pagina. Senza normalizzazione, gli elementi dimensionati con unità viewport si allungherebbero a dimensioni enormi. Il convertitore:

  • Converte tutte le unità relative al viewport in valori fissi in pixel basati sull'altezza originale del viewport
  • Limita immagini e video anormalmente alti a 1.5x l'altezza originale del viewport
  • Gestisce le particolarità di altezza specifiche di Elementor (contenitori flex, effetti di movimento, contenitori di sfondo)
  • Preserva le dimensioni dei video durante il processo di normalizzazione

HTTP Basic Auth#

Passa auth con username e password per catturare pagine protette da HTTP Basic Authentication.

{
    "url": "https://staging.example.com/dashboard",
    "auth": {
        "username": "admin",
        "password": "secret"
    }
}

Inietta fino a 50 cookie prima del caricamento della pagina. Utile per catturare pagine che richiedono una sessione attiva.

{
    "url": "https://example.com/dashboard",
    "cookies": [
        {"name": "session_id", "value": "abc123", "domain": "example.com"},
        {"name": "locale", "value": "en-US", "domain": "example.com"}
    ]
}

Header personalizzati#

Invia fino a 20 header HTTP personalizzati con ogni richiesta alla pagina di destinazione.

{
    "url": "https://example.com/report",
    "headers": {
        "X-Custom-Token": "my-token-value",
        "Accept-Language": "en-US"
    }
}

Caricamento lazy delle immagini#

Quando load_media e enable_scroll sono abilitati (entrambi predefiniti a true), il convertitore scorre la pagina lentamente (120px ogni 90ms) per attivare i loader lazy, poi attende il completamento del caricamento di tutte le immagini con un periodo di stabilizzazione del layout di 500ms.

Imposta load_media=false per una cattura più veloce. Il convertitore usa quindi uno scroll rapido (300px ogni 30ms) con una stabilizzazione più breve di 100ms, ma i contenuti multimediali potrebbero apparire come segnaposto.

Gestione degli header sticky#

Quando abilitata (predefinito true), il convertitore rileva gli elementi con posizionamento fixed e sticky che sembrano essere header, li riposiziona in modalità static per uno screenshot pulito e scorre in cima alla pagina prima della cattura.

Funzionalità di rendering aggiuntive#

  • Emulazione media screen -- La pagina viene renderizzata usando il media CSS screen (non print), quindi lo screenshot corrisponde a ciò che gli utenti vedono nel loro browser.
  • Modalità stealth -- Usa il mascheramento del fingerprint del browser per evitare il rilevamento dei bot su pagine protette.
  • Intercettazione dei popup -- Chiude automaticamente eventuali nuove schede del browser o popup attivati dalla pagina.
  • Bypass CSP -- Gestisce le restrizioni di Content Security Policy e Trusted Types che altrimenti bloccherebbero la manipolazione della pagina.
  • Preservazione delle ombre -- Gli elementi con box-shadow e text-shadow vengono contrassegnati per garantire che le ombre vengano renderizzate correttamente nell'output dello screenshot.

Limitazioni per piano di abbonamento#

Funzionalità Founding Indie Studio Enterprise
Cattura base (singolo URL, sincrona)
Dimensionamento viewport
Modalità asincrona No
Elaborazione batch (più URL) No
Raggruppamento output ZIP No No
Callback webhook No No
HTTP Basic Auth No
Iniezione di cookie No
Header personalizzati No
Conversioni mensili 100 In base al piano In base al piano Illimitate
Limite dimensione batch 0 In base al piano In base al piano Illimitato
Conservazione file 1 ora In base al piano In base al piano In base al piano

Modalità asincrona#

La modalità asincrona è utile per catture di lunga durata o quando si catturano più URL.

Come funziona#

  1. Invia una richiesta con async_mode=true (oppure passa più URL, che abilita automaticamente la modalità asincrona).
  2. L'API restituisce immediatamente HTTP 202 con un batch_id e un url_count.
  3. Ogni URL viene catturato in background, caricato nello storage e tracciato individualmente.
  4. Monitora il completamento tramite polling dello stato batch, notifica email o callback webhook.

Notifica email#

Per impostazione predefinita, viene inviata un'email di completamento all'indirizzo email del proprietario del progetto. Sovrascrivi con notification_email:

{
    "url": ["https://example.com/page1", "https://example.com/page2"],
    "async_mode": true,
    "notification_email": "[email protected]"
}

Callback webhook#

Fornisci un callback_url per ricevere una notifica POST automatica al completamento:

{
    "url": ["https://example.com/page1", "https://example.com/page2"],
    "async_mode": true,
    "callback_url": "https://your-server.com/webhook/enconvert"
}

Elaborazione batch e in blocco#

Cattura più URL in un'unica richiesta. Richiede la modalità asincrona e una chiave privata.

Output individuale (predefinito)#

Ogni URL produce un file PNG separato:

{
    "url": [
        "https://example.com/page1",
        "https://example.com/page2",
        "https://example.com/page3"
    ],
    "async_mode": true
}

Output pacchetto ZIP#

Raggruppa tutti gli screenshot in un unico archivio ZIP:

{
    "url": [
        "https://example.com/page1",
        "https://example.com/page2",
        "https://example.com/page3"
    ],
    "async_mode": true,
    "output_format": true,
    "output_filename": "monthly-screenshots"
}

Esempi di codice#

Python (chiave privata)#

import requests

response = requests.post(
    "https://api.enconvert.com/v1/convert/url-to-screenshot",
    headers={"X-API-Key": "sk_your_private_key"},
    json={
        "url": "https://example.com",
        "viewport_width": 1440,
        "viewport_height": 900
    }
)

data = response.json()
print(data["presigned_url"])

PHP (chiave privata)#

$ch = curl_init("https://api.enconvert.com/v1/convert/url-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",
        "viewport_width" => 1440,
        "viewport_height" => 900
    ])
]);

$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
echo $data["presigned_url"];

Node.js (chiave privata)#

const response = await fetch("https://api.enconvert.com/v1/convert/url-to-screenshot", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "X-API-Key": "sk_your_private_key"
    },
    body: JSON.stringify({
        url: "https://example.com",
        viewport_width: 1440,
        viewport_height: 900
    })
});

const data = await response.json();
console.log(data.presigned_url);

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",
        "viewport_width":  1440,
        "viewport_height": 900,
    })

    req, _ := http.NewRequest("POST", "https://api.enconvert.com/v1/convert/url-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))
}

JavaScript -- Browser (chiave pubblica)#

// Step 1: Get a JWT token
const tokenRes = await fetch("https://api.enconvert.com/v1/auth/token", {
    method: "POST",
    headers: { "X-API-Key": "pk_your_public_key" }
});
const { token } = await tokenRes.json();

// Step 2: Capture screenshot
const convertRes = await fetch("https://api.enconvert.com/v1/convert/url-to-screenshot", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${token}`
    },
    body: JSON.stringify({
        url: "https://example.com"
    })
});

const data = await convertRes.json();
// Display the screenshot
const img = document.createElement("img");
img.src = data.presigned_url;
document.body.appendChild(img);

React (chiave pubblica)#

import { useState } from "react";

function UrlToScreenshot() {
    const [loading, setLoading] = useState(false);
    const [imageUrl, setImageUrl] = useState(null);

    async function captureScreenshot() {
        setLoading(true);
        try {
            // Get JWT token
            const tokenRes = await fetch("https://api.enconvert.com/v1/auth/token", {
                method: "POST",
                headers: { "X-API-Key": "pk_your_public_key" }
            });
            const { token } = await tokenRes.json();

            // Capture screenshot
            const convertRes = await fetch("https://api.enconvert.com/v1/convert/url-to-screenshot", {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    "Authorization": `Bearer ${token}`
                },
                body: JSON.stringify({ url: "https://example.com" })
            });

            const data = await convertRes.json();
            setImageUrl(data.presigned_url);
        } finally {
            setLoading(false);
        }
    }

    return (
        <div>
            <button onClick={captureScreenshot} disabled={loading}>
                {loading ? "Capturing..." : "Take Screenshot"}
            </button>
            {imageUrl && <img src={imageUrl} alt="Screenshot" style={{ maxWidth: "100%" }} />}
        </div>
    );
}

export default UrlToScreenshot;

Risposte di errore#

Stato Condizione
400 Bad Request Parametro url mancante o vuoto
400 Bad Request output_format=true con un singolo URL (richiede più URL)
400 Bad Request direct_download=true con più URL
400 Bad Request direct_download=true con async_mode=true
400 Bad Request Oggetto auth non valido (username o password mancante)
400 Bad Request cookies non valido (non è un array, supera 50 elementi, campi obbligatori mancanti)
400 Bad Request headers non valido (non è un oggetto, supera 20 elementi, nomi di header bloccati, valori non stringa)
400 Bad Request Conflitto tra auth e l'header personalizzato Authorization
400 Bad Request Chiave pubblica che tenta più URL
401 Unauthorized Chiave API o token JWT mancante o non valido
402 Payment Required Quota mensile di ops esaurita
402 Payment Required Il batch supererebbe la quota mensile di ops residua
402 Payment Required Limite di storage raggiunto
403 Forbidden Endpoint non incluso tra quelli consentiti per la chiave API
403 Forbidden Funzionalità non disponibile sul piano attuale (asincrono, webhook, ZIP, basic auth)
403 Forbidden La dimensione del batch supera il limite del piano
404 Not Found ID job non trovato (durante il polling dello stato)
500 Internal Server Error Cattura non riuscita (crash del browser, errore di rendering)

Limiti#

Limite Valore
Timeout di navigazione pagina 60 secondi
Timeout di caricamento per immagine 5 secondi
Timeout di chiusura banner cookie 3 secondi
Massimo cookie per richiesta 50
Massimo header personalizzati per richiesta 20
Operazioni mensili Dipende dal piano (Founding: 500)
Dimensione batch Dipende dal piano (Founding: disabilitato)
Conservazione file Dipende dal piano (Founding: 1 ora)
Timeout di consegna webhook 30 secondi

Domande frequenti#

Come catturo uno screenshot a pagina intera di un sito web con un'API?#

Invia una richiesta POST a /v1/convert/url-to-screenshot con un corpo JSON contenente url, autenticandoti con la tua chiave privata nell'header X-API-Key (oppure con un token Bearer JWT ottenuto da una chiave pubblica). Ogni cattura include l'intero contenuto della pagina, non solo il viewport visibile. Il convertitore ridimensiona il viewport all'altezza completa del contenuto e cattura con full_page=true.

Posso cambiare il formato di output dello screenshot in JPEG o WebP?#

No. Il formato di output non è configurabile. Tutti gli screenshot vengono catturati come immagini PNG a pagina intera.

Come controllo la larghezza e le dimensioni dello screenshot?#

Imposta viewport_width (predefinito 1920). La larghezza dello screenshot corrisponde a questo valore. L'altezza dello screenshot è determinata dall'altezza completa del contenuto della pagina, con viewport_height (predefinito 1080) usato come riferimento per il rendering e il calcolo delle unità viewport.

Posso catturare uno screenshot di una pagina protetta da login?#

Sì. Usa il parametro auth per l'HTTP Basic Auth, inietta fino a 50 cookie di sessione con cookies, oppure invia fino a 20 header HTTP personalizzati con headers. Queste opzioni richiedono l'accesso basic auth sul tuo piano.

Con handle_cookies abilitato (predefinito true), il convertitore chiude automaticamente i banner di consenso di OneTrust, Cookiebot, Didomi, Usercentrics e implementazioni generiche, operando sia sulla pagina principale che sugli iframe. Modali e popup vengono chiusi usando il tasto Escape, pulsanti di chiusura ARIA, pulsanti di chiusura basati su classe e pulsanti di dialogo basati su ruolo, con rimozione degli effetti residui di blur e backdrop.