API Documentation
URL de base : https://glanceshot.com/v1. Tous les endpoints utilisent HTTP standard. Les paramètres peuvent être transmis dans la chaîne de requête (GET) ou dans le corps JSON (POST).
Démarrage rapide
- Inscrivez-vous gratuitement, puis créez une API Key sur la page « API Key » de la console.
- Placez votre API Key dans l’en-tête
X-Access-Key, puis appelez l’endpoint de capture :
curl "https://glanceshot.com/v1/screenshot?url=https://example.com&full_page=true" \
-H "X-Access-Key: $GLANCESHOT_KEY" \
-o screenshot.pngAuthentification
Chaque requête nécessite une API Key, à transmettre de l’une des façons suivantes :
- En-tête
X-Access-Key: gls_…(recommandé pour les appels côté serveur) - Paramètre de requête
access_key=gls_…(uniquement pour les appels côté serveur, à ne pas inclure dans une page web) - URL signée (pour intégrer l’URL dans une page web sans exposer l’API Key ni le secret)
L’API Key n’est affichée en clair qu’une seule fois, lors de sa création. Conservez-la en lieu sûr. En cas de fuite, vous pouvez la désactiver dans la console.
API de capture
/v1/screenshot/v1/screenshotParamètres propres aux captures :
| Paramètre | Type | Par défaut | Description |
|---|---|---|---|
| format | enum | png | png, jpeg ou webp. |
| device_scale_factor | number | 1 | Facteur d’échelle, 1–3. La valeur 2 offre une netteté Retina, pour un fichier environ 4 fois plus volumineux. |
| quality | integer | 80 | Qualité JPEG / WebP, 1–100. |
| full_page | boolean | false | Capture la page entière. Fait défiler la page écran par écran pour déclencher le chargement différé, jusqu’à une hauteur de 20,000 pixels. |
| selector | string | — | Capture uniquement le premier élément correspondant à ce sélecteur CSS. Incompatible avec full_page. |
Paramètres communs aux captures et aux PDF :
| Paramètre | Type | Par défaut | Description |
|---|---|---|---|
| url | string | — | URL de la page à capturer, en http ou https. Utilisez ce paramètre ou html, mais pas les deux. Le fragment # de l’URL est conservé : vous pouvez ainsi capturer directement une page d’une application monopage utilisant le routage par fragment, comme https://app.com/#/report/1. |
| html | string | — | HTML fourni directement (2 MB maximum). Uniquement en POST. |
| viewport_width | integer | 1280 | Largeur de la fenêtre d’affichage, 320–3840. En dessous de 768, le rendu se fait en mode mobile. |
| viewport_height | integer | 800 | Hauteur de la fenêtre d’affichage, 200–3840. |
| wait_until | enum | networkidle | Stratégie d’attente : domcontentloaded (la plus rapide, adaptée aux pages statiques), load, networkidle (suit toutes les requêtes dès l’ouverture de la page et ne lance la capture qu’après 500 millisecondes sans requête en cours une fois la page chargée, avec une attente supplémentaire de 8 secondes maximum ; adaptée aux applications monopages). |
| wait_for_selector | string | — | Après le chargement de la page, attend qu’un élément correspondant à ce sélecteur CSS soit présent et visible avant de lancer la capture, pendant 10 secondes maximum. Sinon, renvoie selector_not_found (non facturé). Adapté aux applications monopages dont le contenu s’affiche après un délai ou une animation, sans requête réseau, comme .chart-ready. |
| delay | integer | 0 | Délai supplémentaire en millisecondes après la fin de l’attente, 0–10000. Utile pour les animations ou les composants chargés à la demande. |
| block_ads | boolean | true | Bloque les requêtes vers les domaines publicitaires et de suivi, et masque les emplacements publicitaires sur la page. |
| block_cookie_banners | boolean | true | Masque les fenêtres de consentement aux cookies. |
| dark_mode | boolean | false | Émule prefers-color-scheme: dark. |
| hide_selectors | string | — | Liste de sélecteurs CSS des éléments à masquer, par exemple .ad,#popup. |
| cache | boolean | true | Indique s’il faut consulter le cache. La valeur false force un nouveau rendu, dont le résultat est tout de même mis en cache. |
| cache_ttl | integer | 86400 | Durée de validité du cache en secondes, 60–2592000. |
| response_type | enum | binary | binary renvoie directement le fichier ; json renvoie l’URL du fichier et les métadonnées. |
| proxy | string | — | Facultatif. Utilisez votre propre proxy pour accéder à la page cible (les frais du proxy restent à votre charge), par exemple pour y accéder depuis un pays ou une région spécifique. Prend en charge socks5:// et http://, avec ou sans identifiants, au format socks5://user:pass@203.0.113.10:1080. Ce paramètre doit figurer uniquement dans le corps d’une requête POST ; il n’est pas disponible pour les requêtes GET, les URL signées ni les tâches par lot. Les requêtes utilisant un proxy sont mises en cache séparément. Si la connexion au proxy ou l’authentification échoue, ou si le proxy ne peut pas accéder au site cible, le code proxy_failed est renvoyé et la requête n’est pas facturée. |
| cookies | string | object[] | — | Cookies du site cible, sous forme d’une ligne comme sid=abc; theme=dark ou d’un tableau comme [{"name":"sid","value":"abc"}] (avec domain et path facultatifs). Ils sont envoyés uniquement au site cible, jamais aux services tiers présents sur la page. |
| headers | object | — | En-têtes de requête à ajouter, par exemple Authorization: Bearer …. Ils sont envoyés uniquement au site cible. Les en-têtes gérés par le navigateur (Host, Cookie, User-Agent, etc.) ne peuvent pas être définis. |
| local_storage | object | — | Données à écrire dans le localStorage de l’origine de l’URL cible. Les clés et les valeurs doivent être des chaînes de caractères. |
| session_storage | object | — | Comme local_storage, mais pour sessionStorage. |
| login_profile | string | — | Identifiant du profil de connexion enregistré via l’extension de navigateur (lp_8f2c…). Plus simple que de transmettre directement les cookies, il peut aussi être utilisé dans les tâches par lots (aucune donnée d’authentification n’est enregistrée dans les tâches). |
Capturer une application monopage (React, Vue, etc.) :Le JavaScript de la page s’exécute dans un véritable navigateur avant la capture. Par défaut, networkidle attend la fin du chargement des données. Si le contenu s’affiche ensuite après un délai ou une animation, ajoutez wait_for_selector pour désigner un élément indiquant que le contenu est prêt. Si aucun élément ne convient, utilisez delay pour prolonger l’attente.
API PDF
/v1/pdf/v1/pdfChaque PDF consomme 2 unités du quota. Avant l’impression, la page est parcourue pour déclencher le chargement différé. En plus des paramètres communs, les paramètres suivants sont disponibles :
| Paramètre | Type | Par défaut | Description |
|---|---|---|---|
| paper | enum | a4 | Format du papier : a4 ou letter. Si la page définit une règle @page, celle-ci est prioritaire. |
| print_background | boolean | true | Imprime les couleurs et les images d’arrière-plan. |
| pdf_media | enum | print utilise les styles d’impression ; screen utilise les styles d’affichage à l’écran (rendu identique à l’écran). |
curl -X POST "https://glanceshot.com/v1/pdf" \
-H "X-Access-Key: $GLANCESHOT_KEY" \
-H "Content-Type: application/json" \
-d '{"html": "<h1>Rapport trimestriel</h1><p>Contenu…</p>", "paper": "a4"}' \
-o report.pdfRéponses
Par défaut (response_type=binary), le fichier est renvoyé directement, avec le Content-Type correspondant au format. En-têtes de réponse :
X-Request-Id: identifiant de la requête, à fournir pour le dépannageX-Glanceshot-Cache:HITouMISSX-Glanceshot-Truncated: true: la capture de la page entière a été tronquée au-delà de 20,000 pixelsX-Glanceshot-Format-Changed: webp: un PNG de plus de 5 MB est automatiquement converti en WebP (sauf si format=png est explicitement spécifié)
Avec response_type=json, la réponse contient l’URL du fichier et les métadonnées :
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"}'
# Renvoie
{
"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 signées
Vous souhaitez intégrer directement l’URL d’une capture dans <img src> sans exposer votre API Key ? L’URL signée ne contient pas l’API Key, mais uniquement l’identifiant public key_id. Vous calculez ensuite la signature sur votre propre serveur à l’aide du secret associé à la clé. L’identifiant de la clé et son secret sont disponibles sur la page API Key de la console :
canonical = Triez tous les paramètres, sauf signature, par ordre lexicographique de leur nom,
formatez chaque entrée en k=urlencode(v) (RFC 3986, espaces encodés en %20), puis reliez-les avec &
signature = hex(HMAC-SHA256(secret, canonical))Une signature valide suffit à authentifier la requête. Toute signature manquante ou incorrecte entraîne son rejet. La modification d’un paramètre (par exemple url) invalide la signature. Le paramètre facultatif expires (horodatage Unix en secondes) est inclus dans le calcul de la signature ; une fois ce délai expiré, l’API renvoie signature_expired. Pour rafraîchir le cache, modifiez un paramètre sans effet sur le résultat (comme v=2), puis recalculez la signature. Les URL signées ne prennent en charge que les appels GET aux endpoints de capture d’écran et de PDF, et n’acceptent pas les paramètres de proxy.
key_id est public et ne permet pas, à lui seul, d’appeler l’API. N’incluez pas l’API Key (access_key) dans une URL signée : sa présence entraîne immédiatement une réponse invalid_params. Si vous avez déjà intégré une API Key dans une page web, désactivez-la dans la console et créez-en une nouvelle.
import crypto from "node:crypto";
// Encodage RFC 3986 (espaces encodés en %20), identique à celui utilisé côté serveur
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="Aperçu de la page web" />Utiliser un proxy
Pour accéder à une page depuis un pays ou une région spécifique (par exemple pour consulter la langue, le contenu et les prix locaux), vous pouvez fournir votre propre proxy dans la requête. Les frais de proxy restent à votre charge. La page, ses images, ses scripts et ses appels API passent tous par ce proxy. Les proxys socks5:// et http:// sont pris en charge, avec ou sans nom d’utilisateur et mot de passe.
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.pngproxydoit figurer uniquement dans le corps d’une requête POST. Il n’est pas accepté dans les requêtes GET, les URL signées ni les tâches par lots, afin d’éviter d’exposer les identifiants du proxy dans une URL, l’historique du navigateur ou une page web.- Si le nom d’utilisateur ou le mot de passe contient des caractères spéciaux comme
@ou:, appliquez-leur un encodage URL (par exemple, remplacez@par%40). - Les requêtes utilisant un proxy disposent d’un cache distinct : leurs résultats ne sont partagés ni avec les requêtes sans proxy ni avec celles utilisant un autre proxy.
- Si la connexion au proxy échoue, si l’authentification échoue ou si le site cible est inaccessible, l’API renvoie
proxy_failed. La requête n’est pas facturée etmessageprécise la cause. - Le proxy doit avoir une adresse publique. Les restrictions sur l’URL cible sont les mêmes qu’en l’absence de proxy : les adresses de réseau privé restent inaccessibles.
- Lorsque vous accédez à un site via un proxy, veuillez respecter ses conditions d’utilisation et la législation locale.
Pages nécessitant une connexion
Pour capturer une page nécessitant une connexion, vous pouvez fournir l’état de connexion de votre propre compte. Deux possibilités : transmettre directement cookies, headers, local_storage et session_storage dans la requête, ou enregistrer cet état dans un « profil de connexion » via l’extension de navigateur Glanceshot et ne transmettre que login_profile dans la requête.
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’extension peut lire les données d’authentification inaccessibles aux scripts de la page (y compris les cookies HttpOnly), ainsi que localStorage et IndexedDB. Elle convient à la plupart des sites. Pour l’installer et la connecter, rendez-vous sur la page « Profils de connexion » de la console.
- L’état de connexion ne peut être transmis que dans le corps d’une requête POST (
GETet les URL signées sont refusés). Il n’est enregistré ni dans les journaux ni dans l’historique des appels. Les requêtes contenant un état de connexion disposent d’un cache propre à cet état, qui n’est pas partagé avec d’autres utilisateurs. - Si un état de connexion est fourni mais que la page redirige vers la page de connexion, l’API renvoie
login_expiredet la requête n’est pas facturée (la connexion a expiré ; synchronisez-la à nouveau avec l’extension). - Pour les sites dont la session est liée à un appareil ou à une IP et dont la connexion ne peut pas être reproduite dans le cloud (par exemple, les services bancaires en ligne), utilisez « Capturer la page actuelle » dans l’extension pour effectuer la capture dans votre propre navigateur, puis la téléverser.
Cache
Les requêtes dont les paramètres sont identiques utilisent le cache (un paramètre omis équivaut à sa valeur par défaut explicite ; les paramètres d’authentification et de cache sont exclus de la comparaison). En cas de résultat en cache, le mode binaire renvoie une redirection 302 vers l’URL du fichier, avec Cache-Control ; le navigateur suit automatiquement la redirection et met le fichier en cache. Le mode JSON renvoie cache_hit: true.
Les résultats servis depuis le cache ne sont pas facturés.Les requêtes simultanées avec les mêmes paramètres ne déclenchent qu’un seul rendu.
Limites et facturation
- Seules les requêtes réussies (2xx) non servies depuis le cache sont facturées : 1 unité pour une capture, 2 pour un PDF.
- Aucun crédit n’est décompté en cas de délai d’attente dépassé, d’échec du rendu, d’erreur ou de blocage d’accès par le site cible, de paramètres invalides ou d’échec de l’authentification.
- Le quota est réinitialisé chaque mois civil (UTC). L’offre gratuite inclut 100 unités par mois ; une fois le quota épuisé, les requêtes renvoient quota_exceeded.
- Tout dépassement du nombre de requêtes par seconde ou de requêtes simultanées renvoie 429. L’en-tête Retry-After indique le délai d’attente conseillé en secondes.
- Durée maximale de rendu : 30 secondes ; volume téléchargé par page : 50 MB maximum ; taille du fichier de sortie : 50 MB maximum.
Consultez les limites de chaque offre : Tarifs.
Codes d’erreur
Toutes les réponses d’erreur sont au format JSON :
{
"error": {
"code": "render_failed",
"message": "target responded with an error status",
"upstream_status": 404,
"request_id": "req_01j…"
}
}| HTTP | code | Signification | Facturé |
|---|---|---|---|
| 400 | invalid_params | Paramètre manquant ou hors limites ; message précise lequel | Non |
| 400 | html_too_large | html dépasse 2 MB | Non |
| 401 | unauthorized | API Key manquante, invalide ou désactivée | Non |
| 401 | signature_invalid | Signature incorrecte (paramètres modifiés ou secret incorrect) | Non |
| 401 | signature_expired | L’URL signée a dépassé la date d’expiration expires | Non |
| 403 | url_blocked | Accès interdit à l’URL cible (par exemple une adresse réseau privée ou localhost) | Non |
| 408 | render_timeout | Le rendu a dépassé 30 secondes | Non |
| 422 | render_failed | Le site cible a renvoyé une erreur 4xx/5xx, une erreur DNS ou une erreur de certificat ; inclut upstream_status | Non |
| 422 | selector_not_found | Aucun élément ne correspond à selector, ou le délai d’attente de wait_for_selector est dépassé | Non |
| 422 | too_many_redirects | Plus de 5 redirections | Non |
| 422 | site_blocked | Le site cible affiche une vérification anti-robot, un CAPTCHA, une page de connexion obligatoire ou un refus d’accès au lieu du contenu attendu ; la requête n’est pas facturée. | Non |
| 422 | login_expired | Un état de connexion a été fourni, mais le site cible affiche toujours la page de connexion : cet état a expiré. | Non |
| 422 | proxy_failed | Impossible de se connecter au proxy fourni, échec de l’authentification ou site cible inaccessible via ce proxy. Le champ message précise la cause. La requête n’est pas facturée. | Non |
| 429 | rate_limited | Limite de requêtes par seconde dépassée ; réessayez en suivant Retry-After | Non |
| 429 | concurrency_exceeded | Limite de requêtes simultanées dépassée | Non |
| 429 | quota_exceeded | Quota mensuel épuisé (offre gratuite) | Non |
| 429 | too_many_batches | Plus de 5 lots en cours | Non |
| 500 | internal | Erreur serveur ; contactez-nous en joignant request_id | Non |
Lots asynchrones
/v1/batch/v1/batch/{id}Envoyez de 1 à 100 URL en une requête. L’endpoint renvoie immédiatement un identifiant de tâche (HTTP 202), puis les captures sont réalisées une par une en arrière-plan. Idéal pour les captures par lots sans garder la connexion ouverte. Vous pouvez interroger régulièrement l’endpoint de suivi ou renseigner webhook_url pour recevoir une notification une fois le traitement terminé. L’authentification est identique à celle des endpoints synchrones (uniquement par en-tête ou paramètre access_key, sans prise en charge des URL signées).
| Paramètre | Type | Par défaut | Description |
|---|---|---|---|
| type | enum | screenshot | screenshot (capture d’écran) ou pdf. |
| urls | string[] | — | URL à traiter, de 1 à 100. Si l’une d’elles est invalide, la requête entière renvoie 400 ; message indique sa position. |
| options | object | {} | Paramètres communs à toutes les URL, identiques à ceux de l’API synchrone (par exemple full_page, format, viewport_width, cache_ttl). Ne doivent pas inclure url, html, response_type, proxy. |
| webhook_url | string | — | Facultatif. URL à notifier une fois le traitement terminé. Voir « Notification de fin ». |
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"
}'
# Renvoie 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 }
]
}Suivi de la progression : le statut status du lot passe par queued (en attente), running (en cours), puis completed (traitement terminé, avec ou sans erreurs). Chaque URL a pour statut pending, running, succeeded ou failed. En cas de réussite, result contient l’URL du fichier ; en cas d’échec, error contient le code d’erreur (identique à ceux des endpoints synchrones).
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" }
}
]
}- La facturation est identique à celle des endpoints synchrones : chaque URL traitée avec succès consomme 1 unité pour une capture ou 2 pour un PDF. Les résultats en cache et les échecs ne consomment pas de quota.
- Si le quota est déjà épuisé lors de l’envoi, la requête renvoie immédiatement
quota_exceeded. S’il s’épuise pendant le traitement, les URL restantes échouent avecquota_exceeded. - Chaque compte peut avoir au maximum 5 lots en cours. Au-delà, la requête renvoie
too_many_batches. - La durée de validité des fichiers est définie par
options.cache_ttl(1 jour par défaut). Téléchargez-les et enregistrez-les avant leur expiration. - Dans les résultats de consultation et les notifications,
webhook.urln’affiche que le chemin, sans la chaîne de requête.
Notification de fin
Si vous renseignez webhook_url, nous y envoyons une requête POST une fois le lot entièrement traité. Le corps JSON est { "event": "batch.completed", "batch": { … } }, où batch est strictement identique à la réponse de l’endpoint de suivi. En-têtes :
X-Glanceshot-Signature: t=1760779812,v1=5d3f…:test l’heure d’envoi (horodatage Unix en secondes) etv1la signatureX-Glanceshot-Event: batch.completed,X-Glanceshot-Delivery-Attempt: 1(numéro de la tentative d’envoi)
v1 = hex(HMAC-SHA256(secret, t + "." + Corps brut de la requête))
secret est le secret de signature associé à l’API Key utilisée pour soumettre la tâche (disponible sur la page API Key de la console).- Renvoyez une réponse 2xx sous 10 secondes, sinon l’envoi est considéré comme ayant échoué. En cas d’échec, trois nouvelles tentatives sont effectuées après 10 secondes, 1 minute et 5 minutes (4 tentatives au maximum au total).
- Dans de très rares cas, vous pouvez recevoir plusieurs notifications pour une même tâche. Dédupliquez-les à l’aide de
batch.id. - Pour vérifier la signature, utilisez les octets bruts reçus et assurez-vous que
tne diffère pas de l’heure actuelle de plus de quelques minutes afin d’éviter les attaques par rejeu. - L’URL de callback doit être une adresse http(s) accessible publiquement et ne doit pas pointer vers un réseau privé.
import crypto from "node:crypto";
// rawBody doit contenir les octets bruts reçus, sans passer par JSON.parse puis une nouvelle sérialisation.
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; // Protection contre le rejeu
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)Suivi de l’utilisation
/v1/usagecurl "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", ... }État du service
/v1/healthSans authentification. Renvoie l’état du nœud et du pool de navigateurs (nombre total, occupés et disponibles).