Glanceshot
Documentazione per sviluppatori

API Documentazione

URL di base: https://glanceshot.com/v1. Tutti gli endpoint usano HTTP standard. I parametri possono essere passati nella query string (GET) o nel corpo JSON (POST).

Guida rapida

  1. Registrati gratis e crea un'API Key nella pagina «API Key» della console.
  2. Inserisci l'API Key nell'header X-Access-Key e chiama l'endpoint screenshot:
curl "https://glanceshot.com/v1/screenshot?url=https://example.com&full_page=true" \
  -H "X-Access-Key: $GLANCESHOT_KEY" \
  -o screenshot.png

Autenticazione

Ogni richiesta richiede un'API Key, che puoi passare in uno dei seguenti modi:

  • Header X-Access-Key: gls_… (consigliato per le chiamate lato server)
  • Parametro di query access_key=gls_… (solo per chiamate lato server, non inserirlo nelle pagine web)
  • URL firmato (per inserire l'indirizzo in una pagina web senza esporre né l'API Key né il secret)

L'API Key viene mostrata in chiaro una sola volta, al momento della creazione. Conservala al sicuro. Se viene compromessa, puoi disattivarla dalla console.

Endpoint screenshot

GET/v1/screenshot
POST/v1/screenshot

Parametri specifici per gli screenshot:

ParametroTipoValore predefinitoDescrizione
formatenumpngpng, jpeg o webp.
device_scale_factornumber1Fattore di scala, 1–3. Impostando 2 si ottiene una risoluzione Retina, con dimensioni del file circa 4 volte maggiori.
qualityinteger80Qualità JPEG / WebP, 1–100.
full_pagebooleanfalseAcquisisce l'intera pagina. Scorre una schermata alla volta per attivare il caricamento differito, fino a un'altezza massima di 20,000 pixel.
selectorstring—Acquisisce solo il primo elemento corrispondente a questo selettore CSS. Non può essere usato insieme a full_page.

Parametri comuni a screenshot e PDF:

ParametroTipoValore predefinitoDescrizione
urlstring—URL della pagina da acquisire, http o https. Usa questo parametro oppure html. Il frammento # dell'URL viene mantenuto: puoi acquisire direttamente la pagina desiderata nelle applicazioni a pagina singola con routing hash, come https://app.com/#/report/1.
htmlstring—HTML da inviare direttamente (massimo 2 MB). Supportato solo con POST.
viewport_widthinteger1280Larghezza del viewport, 320–3840. Con valori inferiori a 768, la pagina viene renderizzata come su un dispositivo mobile.
viewport_heightinteger800Altezza del viewport, 200–3840.
wait_untilenumnetworkidleStrategia di attesa: domcontentloaded (la più rapida, ideale per pagine statiche), load, networkidle (monitora tutte le richieste dall'apertura della pagina e, dopo il caricamento, acquisisce lo screenshot quando non ci sono richieste in corso per 500 millisecondi consecutivi; attende al massimo altri 8 secondi, ideale per applicazioni a pagina singola).
wait_for_selectorstring—Dopo il caricamento della pagina, attende fino a 10 secondi che un elemento corrispondente a questo selettore CSS sia presente e visibile prima di acquisire lo screenshot. Se non compare, restituisce selector_not_found (senza addebito). Ideale per applicazioni a pagina singola che renderizzano contenuti in ritardo tramite timer o animazioni, anziché richieste di rete, come .chart-ready.
delayinteger0Ritardo aggiuntivo in millisecondi dopo l'attesa, 0–10000. Utile per animazioni o componenti con caricamento differito.
block_adsbooleantrueBlocca le richieste ai domini pubblicitari e di tracciamento e nasconde gli spazi pubblicitari nella pagina.
block_cookie_bannersbooleantrueNasconde i banner di consenso ai cookie.
dark_modebooleanfalseSimula prefers-color-scheme: dark.
hide_selectorsstring—Elenco di selettori CSS degli elementi da nascondere, ad esempio .ad,#popup.
cachebooleantrueIndica se cercare nella cache. Con false forza un nuovo rendering; il risultato viene comunque salvato nella cache.
cache_ttlinteger86400Durata della cache in secondi, 60–2592000.
response_typeenumbinarybinary restituisce direttamente il file; json restituisce l'URL del file e i metadati.
proxystring—Facoltativo. Usa un proxy acquistato da te per accedere alla pagina di destinazione (i costi del proxy sono a tuo carico), ad esempio per accedere da un paese o una regione specifici. Supporta socks5:// e http://, anche con nome utente e password, nel formato socks5://user:pass@203.0.113.10:1080. Può essere specificato solo nel corpo di una richiesta POST, non nelle richieste GET, negli URL firmati o nelle operazioni in batch. Le richieste tramite proxy hanno una cache separata; se il proxy non è raggiungibile, l'autenticazione fallisce o il sito di destinazione non è accessibile tramite il proxy, viene restituito proxy_failed senza alcun addebito.
cookiesstring | object[]—Cookie del sito di destinazione, come singola riga nel formato sid=abc; theme=dark oppure come array nel formato [{"name":"sid","value":"abc"}] (con domain e path facoltativi). Vengono inviati solo al sito di destinazione, non alle terze parti presenti nella pagina.
headersobject—Header da aggiungere alla richiesta, ad esempio Authorization: Bearer …. Vengono inviati solo al sito di destinazione; non è possibile impostare quelli gestiti dal browser (Host, Cookie, User-Agent, ecc.).
local_storageobject—Dati da scrivere nel localStorage dell'origine dell'URL di destinazione. Chiavi e valori devono essere stringhe.
session_storageobject—Come local_storage, ma scrive in sessionStorage.
login_profilestring—ID del profilo di accesso salvato con l'estensione del browser (lp_8f2c…). È più pratico che passare direttamente i cookie e funziona anche nelle operazioni in batch (che non memorizzano alcuna credenziale).

Acquisire applicazioni a pagina singola (React, Vue, ecc.):La pagina viene eseguita in un browser reale e lo screenshot viene acquisito dopo l'esecuzione di JavaScript. La strategia predefinita networkidle attende il completamento del recupero dei dati. Se i contenuti vengono renderizzati con timer o animazioni dopo la fine delle richieste, aggiungi wait_for_selector per indicare un elemento che segnali che il contenuto è pronto. Se non c'è un elemento adatto, usa delay per attendere ancora.

Endpoint PDF

GET/v1/pdf
POST/v1/pdf

Ogni PDF consuma 2 crediti. Prima della stampa, la pagina viene scorsa per attivare i contenuti con caricamento differito. Oltre ai parametri comuni, sono supportati:

ParametroTipoValore predefinitoDescrizione
paperenuma4Formato carta: a4 o letter. Se la pagina definisce regole @page, queste hanno la precedenza.
print_backgroundbooleantrueStampa colori e immagini di sfondo.
pdf_mediaenumprintprint usa gli stili di stampa; screen usa gli stili a schermo (come visualizzati nel browser).
Da HTML a PDF
curl -X POST "https://glanceshot.com/v1/pdf" \
  -H "X-Access-Key: $GLANCESHOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"html": "<h1>Report trimestrale</h1><p>Contenuto…</p>", "paper": "a4"}' \
  -o report.pdf

Risposte

Per impostazione predefinita (response_type=binary), viene restituito direttamente il file con il Content-Type del formato corrispondente. Header della risposta:

  • X-Request-Id: ID della richiesta, da fornire per la risoluzione dei problemi
  • X-Glanceshot-Cache: HIT o MISS
  • X-Glanceshot-Truncated: true: la pagina intera è stata troncata perché supera 20,000 pixel
  • X-Glanceshot-Format-Changed: webp: un PNG superiore a 5 MB è stato convertito automaticamente in WebP (nessuna conversione se format=png è specificato esplicitamente)

Impostando response_type=json, vengono restituiti l'URL del file e i metadati:

Risposta JSON
curl -X POST "https://glanceshot.com/v1/screenshot" \
  -H "X-Access-Key: $GLANCESHOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com", "response_type": "json"}'

# Risposta
{
  "url": "https://glanceshot.com/i/3f/3f9c….png",
  "cache_hit": false,
  "duration_ms": 1284,
  "format": "png",
  "width": 1280,
  "height": 800,
  "request_id": "req_01j…"
}

URL firmati

Vuoi inserire l'URL dello screenshot direttamente in <img src> senza esporre l'API Key? L'URL firmato contiene solo il key_id pubblico, non l'API Key. La firma viene calcolata sul tuo server usando il secret associato alla chiave. Trovi Key ID e secret nella pagina API Key della console:

Regole di firma
canonical = Ordina tutti i parametri, tranne signature, in ordine lessicografico per nome.
            Codifica ogni coppia come k=urlencode(v) (RFC 3986, con gli spazi codificati come %20) e uniscile con &
signature = hex(HMAC-SHA256(secret, canonical))

Una firma valida autentica la richiesta; le richieste con firma mancante o non valida vengono rifiutate. Qualsiasi modifica ai parametri (ad esempio a url) invalida la firma. Il parametro facoltativo expires (timestamp Unix in secondi) è incluso nella firma; dopo la scadenza viene restituito signature_expired. Per aggiornare la cache, basta modificare un parametro senza effetto (come v=2) e ricalcolare la firma. Gli URL firmati supportano solo richieste GET agli endpoint per screenshot e PDF e non possono includere parametri proxy.

key_id è pubblico e da solo non consente di chiamare l'API. Non inserire l'API Key (access_key) nell'URL firmato: se presente, viene restituito subito invalid_params. Se hai già inserito un'API Key in una pagina web, disattivala nella console e creane una nuova.

import crypto from "node:crypto";

// Codifica RFC 3986 (spazi come %20), conforme alle regole del server
const enc = (v) =>
  encodeURIComponent(v).replace(/[!'()*]/g, (c) => "%" + c.charCodeAt(0).toString(16).toUpperCase());

function signedUrl(params, keyId, secret) {
  const all = { ...params, key_id: keyId };
  const canonical = Object.keys(all).sort().map((k) => `${k}=${enc(String(all[k]))}`).join("&");
  const signature = crypto.createHmac("sha256", secret).update(canonical).digest("hex");
  return `https://glanceshot.com/v1/screenshot?${canonical}&signature=${signature}`;
}

const src = signedUrl({ url: "https://example.com", viewport_width: 1200 }, KEY_ID, SECRET);
// <img src={src} alt="Anteprima della pagina web" />

Uso dei proxy

Se devi accedere a una pagina da un paese o un'area geografica specifici (ad esempio per visualizzare lingua, contenuti e prezzi locali), puoi includere nella richiesta un proxy acquistato da te, a tue spese. La pagina e tutte le relative immagini, script e richieste API verranno caricati tramite questo proxy. Sono supportati i proxy socks5:// e http://, anche con nome utente e password.

curl -X POST "https://glanceshot.com/v1/screenshot" \
  -H "X-Access-Key: $GLANCESHOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com", "proxy": "socks5://user:pass@203.0.113.10:1080"}' \
  -o screenshot.png
  • proxy può essere incluso solo nel corpo di una richiesta POST: non è consentito nelle richieste GET, negli URL firmati o nelle operazioni in batch, per evitare che le credenziali del proxy compaiano negli URL, nella cronologia del browser o nelle pagine web.
  • Se il nome utente o la password contengono caratteri speciali come @ o :, devi prima applicare la codifica URL (ad esempio, @ diventa %40).
  • Le richieste con proxy vengono memorizzate in una cache separata e non condividono i risultati con richieste senza proxy o con proxy diversi.
  • Se la connessione al proxy o l'autenticazione falliscono, oppure il sito di destinazione non è raggiungibile, viene restituito proxy_failed senza alcun addebito. message indica il motivo specifico.
  • Il proxy deve avere un indirizzo pubblico. Per l'URL di destinazione valgono le stesse restrizioni delle richieste senza proxy: non è consentito accedere a indirizzi di rete privata.
  • Quando accedi a un sito tramite proxy, rispetta i termini d'uso del sito e le leggi locali.

Pagine con accesso richiesto

Per acquisire pagine che richiedono l'accesso, puoi fornire i dati della sessione del tuo account. Hai due possibilità: passare cookies, headers, local_storage e session_storage direttamente nella richiesta, oppure usare l'estensione Glanceshot per salvare la sessione in un «profilo di accesso» e includere nella richiesta solo login_profile.

curl -X POST "https://glanceshot.com/v1/screenshot"   -H "X-Access-Key: $GLANCESHOT_KEY"   -H "Content-Type: application/json"   -d '{
    "url": "https://app.example.com/dashboard",
    "cookies": "sid=YOUR_SESSION; theme=dark",
    "local_storage": {"token": "YOUR_TOKEN"}
  }' -o screenshot.png
  • L'estensione può leggere le credenziali di accesso non accessibili agli script della pagina (inclusi i Cookie HttpOnly), oltre a localStorage e IndexedDB, ed è adatta alla maggior parte dei siti. Per installarla e collegarla, vai alla pagina «Profili di accesso» della console.
  • I dati di accesso possono essere trasmessi solo nel corpo di una richiesta POST (GET e gli URL firmati vengono rifiutati) e non vengono salvati nei log né nella cronologia delle chiamate. Le richieste con dati di accesso vengono memorizzate in una cache separata in base a tali dati, mai condivisa con altri utenti.
  • Se fornisci i dati di accesso ma la pagina reindirizza al login, viene restituito login_expired senza alcun addebito: la sessione non è più valida e va sincronizzata di nuovo tramite l'estensione.
  • Per i siti che legano la sessione al dispositivo o all'IP e non consentono di riprodurre l'accesso nel cloud (ad esempio i servizi bancari online), usa «Acquisisci la pagina corrente» nell'estensione per acquisire lo screenshot nel tuo browser e poi caricarlo.

Cache

Le richieste con gli stessi parametri usano la cache (omettere un parametro equivale a specificarne il valore predefinito; i parametri di autenticazione e della cache sono esclusi dal confronto). In caso di riscontro nella cache, la modalità binaria restituisce un reindirizzamento 302 all'URL del file con Cache-Control: il browser segue automaticamente il reindirizzamento e memorizza il file nella cache. La modalità JSON restituisce cache_hit: true.

Le risposte dalla cache non vengono addebitate.Le richieste simultanee con gli stessi parametri generano un solo rendering.

Limiti e addebiti

  • Vengono addebitate solo le richieste riuscite (2xx) non servite dalla cache: 1 credito per screenshot, 2 crediti per PDF.
  • Timeout, errori di rendering, errori o blocchi di accesso del sito di destinazione, parametri non validi e autenticazione non riuscita non consumano crediti.
  • I crediti si rinnovano ogni mese solare (UTC). Il piano gratuito include 100 crediti al mese; una volta esauriti, viene restituito quota_exceeded.
  • Se superi il limite di richieste al secondo o di richieste simultanee, viene restituito 429. L'header Retry-After indica quanti secondi attendere prima di riprovare.
  • Durata massima di un rendering: 30 secondi. Download massimo per pagina: 50 MB. Dimensione massima del file generato: 50 MB.

Consulta i limiti di ogni piano: Prezzi.

Codici di errore

Tutte le risposte di errore sono in JSON:

Formato degli errori
{
  "error": {
    "code": "render_failed",
    "message": "target responded with an error status",
    "upstream_status": 404,
    "request_id": "req_01j…"
  }
}
HTTPcodeSignificatoAddebitato
400invalid_paramsParametro mancante o fuori intervallo; message indica qualeNo
400html_too_largehtml supera 2 MBNo
401unauthorizedAPI Key mancante, non valida o disattivataNo
401signature_invalidFirma non corrispondente (parametri modificati o secret errato)No
401signature_expiredL'URL firmato ha superato la scadenza expiresNo
403url_blockedAccesso all'indirizzo di destinazione non consentito (ad esempio indirizzi di rete interna o localhost)No
408render_timeoutIl rendering ha superato 30 secondiNo
422render_failedIl sito di destinazione ha restituito 4xx/5xx, la risoluzione DNS è fallita o si è verificato un errore di certificato; include upstream_statusNo
422selector_not_foundselector non corrisponde ad alcun elemento oppure l'attesa di wait_for_selector è scadutaNo
422too_many_redirectsSuperato il limite di 5 reindirizzamentiNo
422site_blockedIl sito di destinazione mostra una verifica anti-bot, un CAPTCHA, una schermata di accesso o una pagina di accesso negato anziché il contenuto previsto; la richiesta non viene addebitata.No
422login_expiredSono stati forniti dati di accesso, ma il sito di destinazione mostra ancora la pagina di login: la sessione non è più valida.No
422proxy_failedIl proxy fornito non è raggiungibile, l'autenticazione è fallita oppure il sito di destinazione non è accessibile tramite il proxy. message indica la causa specifica. Nessun addebito.No
429rate_limitedSuperato il limite di richieste al secondo; riprova seguendo Retry-AfterNo
429concurrency_exceededSuperato il limite di richieste simultaneeNo
429quota_exceededCrediti mensili esauriti (piano gratuito)No
429too_many_batchesSuperato il limite di 5 batch in corsoNo
500internalErrore del server. Contattaci fornendo request_idNo

Batch asincroni

POST/v1/batch
GET/v1/batch/{id}

Invia da 1 a 100 URL in una sola richiesta: l'endpoint restituisce subito un ID attività (HTTP 202) e acquisisce gli screenshot uno alla volta in background. Ideale per acquisizioni in batch senza mantenere aperta la connessione. Puoi interrogare periodicamente l'endpoint di stato oppure specificare webhook_url per ricevere una notifica al completamento. L'autenticazione è la stessa degli endpoint sincroni (solo tramite header o parametro access_key; gli URL firmati non sono supportati).

ParametroTipoValore predefinitoDescrizione
typeenumscreenshotscreenshot (screenshot) o pdf.
urlsstring[]—URL da elaborare, da 1 a 100. Se anche uno solo non è valido, l'intera richiesta restituisce 400; message ne indica la posizione.
optionsobject{}Parametri comuni a tutti gli URL, gli stessi dell'API sincrona (ad esempio full_page, format, viewport_width, cache_ttl). Non possono includere url, html, response_type, proxy.
webhook_urlstring—Facoltativo. URL a cui inviare la notifica al termine di tutte le elaborazioni. Vedi «Webhook di completamento».
Inviare un batch
curl -X POST "https://glanceshot.com/v1/batch" \
  -H "X-Access-Key: $GLANCESHOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "screenshot",
    "urls": ["https://example.com", "https://example.org"],
    "options": { "full_page": true, "format": "webp" },
    "webhook_url": "https://your-app.com/hooks/glanceshot"
  }'

# Risposta 202
{
  "id": "bat_01j…",
  "type": "screenshot",
  "status": "queued",
  "total": 2, "succeeded": 0, "failed": 0,
  "created_at": "2026-10-18T09:30:00Z", "completed_at": null,
  "webhook": { "url": "https://your-app.com/hooks/glanceshot", "status": "none", "attempts": 0 },
  "items": [
    { "index": 0, "url": "https://example.com", "status": "pending", "result": null, "error": null },
    { "index": 1, "url": "https://example.org", "status": "pending", "result": null, "error": null }
  ]
}

Verifica l'avanzamento: lo stato status dell'attività passa da queued (in coda) a running (in elaborazione), fino a completed (tutte le elaborazioni terminate, riuscite o meno). Ogni URL ha uno stato tra pending, running, succeeded e failed. In caso di successo, result contiene l'URL del file; in caso di errore, error contiene il codice di errore (gli stessi degli endpoint sincroni).

Verificare lo stato di un batch
curl "https://glanceshot.com/v1/batch/bat_01j…" -H "X-Access-Key: $GLANCESHOT_KEY"

{
  "id": "bat_01j…",
  "status": "completed",
  "total": 2, "succeeded": 1, "failed": 1,
  "completed_at": "2026-10-18T09:30:12Z",
  "items": [
    {
      "index": 0, "url": "https://example.com", "status": "succeeded", "duration_ms": 1830,
      "result": { "url": "https://glanceshot.com/i/3f/3f9c….webp", "mime": "image/webp", "width": 1280, "height": 2410, "cache_hit": false },
      "error": null
    },
    {
      "index": 1, "url": "https://example.org", "status": "failed", "duration_ms": 640,
      "result": null,
      "error": { "code": "render_failed", "message": "target responded with an error status" }
    }
  ]
}
  • Gli addebiti seguono le stesse regole degli endpoint sincroni: ogni URL elaborato con successo consuma 1 credito per screenshot o 2 per PDF. Le risposte dalla cache e le elaborazioni non riuscite non consumano crediti.
  • Se i crediti sono già esauriti al momento dell'invio, viene restituito subito quota_exceeded. Se si esauriscono durante l'elaborazione, gli URL rimanenti falliscono con quota_exceeded.
  • Ogni account può avere al massimo 5 batch in corso. Oltre questo limite viene restituito too_many_batches.
  • La validità dei file generati è determinata da options.cache_ttl (1 giorno per impostazione predefinita). Scaricali e salvali prima della scadenza.
  • Nelle risposte di stato e nei webhook, webhook.url viene mostrato solo fino al percorso, senza la query string.

Webhook di completamento

Se specifichi webhook_url, al completamento di tutte le elaborazioni inviamo a quell'URL una richiesta POST con corpo JSON: { "event": "batch.completed", "batch": { … } }. Il campo batch è identico alla risposta dell'endpoint di stato. Header della richiesta:

  • X-Glanceshot-Signature: t=1760779812,v1=5d3f…: t è l'ora di invio (secondi Unix), v1 è la firma
  • X-Glanceshot-Event: batch.completed, X-Glanceshot-Delivery-Attempt: 1 (numero del tentativo di invio)
Regole di firma
v1 = hex(HMAC-SHA256(secret, t + "." + Corpo originale della richiesta))
secret è il segreto di firma associato all’API Key usata per inviare il task (disponibile nella pagina API Key della console)
  • Restituisci una risposta 2xx entro 10 secondi, altrimenti l’invio sarà considerato fallito. In caso di errore, verranno effettuati nuovi tentativi dopo 10 secondi, 1 minuto e 5 minuti (fino a 4 tentativi in totale).
  • In casi molto rari potresti ricevere notifiche duplicate per lo stesso task. Usa batch.id per deduplicarle.
  • Per verificare la firma, calcolala sui byte originali ricevuti e controlla che t non differisca dall’ora corrente di più di qualche minuto, per prevenire attacchi replay.
  • L’indirizzo di callback deve essere un indirizzo http(s) accessibile pubblicamente e non può puntare a una rete privata.
import crypto from "node:crypto";

// rawBody deve contenere i byte originali ricevuti, senza eseguire prima JSON.parse e poi serializzare di nuovo
function verifyGlanceshotWebhook(rawBody, header, secret, toleranceSec = 300) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const t = Number(parts.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false; // Protezione dagli attacchi replay
  const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  const got = Buffer.from(parts.v1 ?? "");
  return got.length === expected.length && crypto.timingSafeEqual(Buffer.from(expected), got);
}

// verifyGlanceshotWebhook(req.rawBody, req.headers["x-glanceshot-signature"], GLANCESHOT_SECRET)

Verifica dei consumi

GET/v1/usage
shell
curl "https://glanceshot.com/v1/usage" -H "X-Access-Key: $GLANCESHOT_KEY"

{ "month": "202610", "used": 37, "limit": 100, "remaining": 63, "overage": 0, "resets_at": "2026-11-01T00:00:00Z", ... }

Controllo di stato

GET/v1/health

Non richiede autenticazione. Restituisce lo stato del nodo e del pool di browser (totali, occupati, disponibili).