API Dokumentation
Basis-URL: https://yhfdghkh6544.com/v1. Alle Endpunkte verwenden Standard-HTTP. Parameter können im Query-String (GET) oder im JSON-Body (POST) übergeben werden.
Schnellstart
- Registrieren Sie sich kostenlos und erstellen Sie in der Konsole unter „API Key“ einen API Key.
- Übergeben Sie den API Key im Request-Header
X-Access-Keyund rufen Sie den Screenshot-Endpunkt auf:
curl "https://yhfdghkh6544.com/v1/screenshot?url=https://example.com&full_page=true" \
-H "X-Access-Key: $SNAPI_KEY" \
-o screenshot.pngAuthentifizierung
Jede Anfrage benötigt einen API Key. Sie können ihn auf eine der folgenden Arten übergeben:
- Request-Header
X-Access-Key: snp_…(empfohlen für serverseitige Aufrufe) - Query-Parameter
access_key=snp_… - Signierte URL (zum Einbetten der URL in Webseiten, ohne das Secret offenzulegen)
Der API Key wird nur bei der Erstellung einmal im Klartext angezeigt. Bewahren Sie ihn sicher auf. Bei einer Offenlegung können Sie ihn in der Konsole deaktivieren.
Screenshot-Endpunkt
/v1/screenshot/v1/screenshotScreenshot-spezifische Parameter:
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
| format | enum | png | png, jpeg oder webp. |
| device_scale_factor | number | 1 | Skalierungsfaktor 1–3. Mit 2 erhalten Sie Retina-Schärfe bei etwa 4-facher Dateigröße. |
| quality | integer | 80 | JPEG / WebP-Qualität, 1–100. |
| full_page | boolean | false | Nimmt die gesamte Seite auf. Scrollt Bildschirm für Bildschirm, um Lazy Loading auszulösen. Maximale Höhe: 20,000 Pixel. |
| selector | string | — | Nimmt nur das erste Element auf, das diesem CSS-Selektor entspricht. Nicht mit full_page kombinierbar. |
Gemeinsame Parameter für Screenshots und PDFs:
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
| url | string | — | URL der aufzunehmenden Webseite, http oder https. Geben Sie entweder diesen Parameter oder html an. Das #-Fragment der URL bleibt erhalten. So können Sie Seiten von Single-Page-Anwendungen mit Hash-Routing (z. B. https://app.com/#/report/1) direkt aufnehmen. |
| html | string | — | HTML direkt übergeben (maximal 2 MB), nur per POST. |
| viewport_width | integer | 1280 | Viewport-Breite, 320–3840. Bei Werten unter 768 wird die Seite wie auf einem Mobilgerät gerendert. |
| viewport_height | integer | 800 | Viewport-Höhe, 200–3840. |
| wait_until | enum | networkidle | Wartestrategie: domcontentloaded (am schnellsten, für statische Seiten), load, networkidle (verfolgt alle Anfragen ab dem Öffnen der Seite; nach dem Laden wird der Screenshot erstellt, sobald 500 Millisekunden lang keine Anfrage mehr läuft; wartet höchstens weitere 8 Sekunden, geeignet für Single-Page-Anwendungen). |
| wait_for_selector | string | — | Wartet nach dem Laden der Seite bis zu 10 Sekunden, bis ein Element erscheint und sichtbar ist, das diesem CSS-Selektor entspricht. Andernfalls wird selector_not_found zurückgegeben (ohne Berechnung). Geeignet für Single-Page-Anwendungen, die Inhalte per Timer oder Animation verzögert rendern, ohne Netzwerkanfragen auszulösen, z. B. .chart-ready. |
| delay | integer | 0 | Zusätzliche Wartezeit in Millisekunden nach Abschluss der Wartestrategie, 0–10000. Für Animationen oder Lazy-Loading-Komponenten. |
| block_ads | boolean | true | Blockiert Anfragen an Werbe- und Tracking-Domains. |
| block_cookie_banners | boolean | true | Blendet Cookie-Einwilligungsdialoge aus. |
| dark_mode | boolean | false | Simuliert prefers-color-scheme: dark. |
| hide_selectors | string | — | Liste von CSS-Selektoren für auszublendende Elemente, z. B. .ad,#popup. |
| cache | boolean | true | Legt fest, ob der Cache geprüft wird. Mit false wird die Seite neu gerendert; das Ergebnis wird weiterhin im Cache gespeichert. |
| cache_ttl | integer | 86400 | Cache-Gültigkeitsdauer in Sekunden, 60–2592000. |
| response_type | enum | binary | binary gibt die Datei direkt zurück; json gibt die Datei-URL und Metadaten zurück. |
Single-Page-Anwendungen aufnehmen (React, Vue usw.):Die Seite führt JavaScript in einem echten Browser aus, bevor der Screenshot erstellt wird. Die Standardstrategie networkidle wartet, bis die Seite ihre Daten geladen hat. Werden Inhalte erst danach per Timer oder Animation gerendert, geben Sie mit wait_for_selector ein Element an, das signalisiert, dass der Inhalt bereit ist. Gibt es kein geeignetes Element, können Sie mit delay zusätzliche Wartezeit einplanen.
PDF-Endpunkt
/v1/pdf/v1/pdfJedes PDF verbraucht 2 Kontingenteinheiten. Vor dem Drucken wird die Seite einmal durchgescrollt, um Lazy-Loading-Inhalte zu laden. Zusätzlich zu den gemeinsamen Parametern werden unterstützt:
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
| paper | enum | a4 | Papierformat: a4 oder letter. Enthält die Seite eine eigene @page-Regel, hat diese Vorrang. |
| print_background | boolean | true | Druckt Hintergrundfarben und -bilder. |
| pdf_media | enum | print verwendet Druckstile; screen verwendet Bildschirmstile (wie im Browser angezeigt). |
curl -X POST "https://yhfdghkh6544.com/v1/pdf" \
-H "X-Access-Key: $SNAPI_KEY" \
-H "Content-Type: application/json" \
-d '{"html": "<h1>Quartalsbericht</h1><p>Inhalt …</p>", "paper": "a4"}' \
-o report.pdfAntworten
Standardmäßig (response_type=binary) wird die Datei direkt zurückgegeben, mit dem passenden Format in Content-Type. Response-Header:
X-Request-Id: ID dieser Anfrage; bitte bei der Fehleranalyse angebenX-Snapi-Cache:HIToderMISSX-Snapi-Truncated: true: Die vollständige Seite wurde bei 20,000 Pixeln Höhe abgeschnittenX-Snapi-Format-Changed: webp: PNG über 5 MB wurde automatisch in WebP umgewandelt (keine Umwandlung bei expliziter Angabe von format=png)
Mit response_type=json werden die Datei-URL und Metadaten zurückgegeben:
curl -X POST "https://yhfdghkh6544.com/v1/screenshot" \
-H "X-Access-Key: $SNAPI_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "response_type": "json"}'
# Rückgabe
{
"url": "https://yhfdghkh6544.com/i/3f/3f9c….png",
"cache_hit": false,
"duration_ms": 1284,
"format": "png",
"width": 1280,
"height": 800,
"request_id": "req_01j…"
}Signierte URLs
Sie möchten die Screenshot-URL direkt in <img src> einbinden, ohne Ihren API Key offenzulegen? Berechnen Sie die Signatur auf Ihrem eigenen Server mit dem zum API Key gehörenden Secret. Sie finden es in der Konsole unter „API Key“:
canonical = Alle Parameter außer signature lexikografisch nach Parameternamen sortieren,
jeden Eintrag als k=urlencode(v) kodieren (RFC 3986, Leerzeichen als %20) und mit & verbinden
signature = hex(HMAC-SHA256(secret, canonical))Eine gültige Signatur authentifiziert die Anfrage. Wird ein Parameter geändert (z. B. url), wird die Signatur ungültig. Der optionale Parameter expires (Unix-Zeit in Sekunden) wird in die Signatur einbezogen; nach Ablauf wird signature_expired zurückgegeben. Um den Cache zu aktualisieren, ändern Sie einen Parameter ohne funktionale Bedeutung (z. B. v=2) und signieren Sie die URL erneut. Signierte URLs unterstützen nur GET.
import crypto from "node:crypto";
// RFC-3986-Kodierung (Leerzeichen als %20), muss den serverseitigen Regeln entsprechen
const enc = (v) =>
encodeURIComponent(v).replace(/[!'()*]/g, (c) => "%" + c.charCodeAt(0).toString(16).toUpperCase());
function signedUrl(params, accessKey, secret) {
const all = { ...params, access_key: accessKey };
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://yhfdghkh6544.com/v1/screenshot?${canonical}&signature=${signature}`;
}
const src = signedUrl({ url: "https://example.com", viewport_width: 1200 }, KEY, SECRET);
// <img src={src} alt="Webseitenvorschau" />Cache
Anfragen mit identischen Parametern werden aus dem Cache bedient. Weggelassene Parameter gelten als identisch mit explizit angegebenen Standardwerten; Authentifizierungs- und Cache-Parameter werden nicht verglichen. Bei einem Cache-Treffer liefert der Binärmodus eine 302-Weiterleitung zur Datei-URL mit Cache-Control. Der Browser folgt der Weiterleitung automatisch und speichert die Datei im Cache. Im JSON-Modus wird cache_hit: true zurückgegeben.
Cache-Treffer werden nicht berechnet.Gleichzeitige Anfragen mit identischen Parametern lösen nur einen Rendervorgang aus.
Limits und Abrechnung
- Nur erfolgreiche Anfragen (2xx) ohne Cache-Treffer werden berechnet: 1 Kontingenteinheit pro Screenshot, 2 pro PDF.
- Zeitüberschreitungen, Renderfehler, Fehler der Zielwebsite, ungültige Parameter und fehlgeschlagene Authentifizierungen verbrauchen kein Kontingent.
- Das Kontingent wird zu Beginn jedes Kalendermonats (UTC) zurückgesetzt. Der kostenlose Tarif enthält 100 Kontingenteinheiten pro Monat. Nach Verbrauch wird quota_exceeded zurückgegeben.
- Bei Überschreitung der Anfragen pro Sekunde oder der gleichzeitigen Anfragen wird 429 zurückgegeben. Der Response-Header Retry-After enthält die empfohlene Wartezeit in Sekunden.
- Maximale Renderdauer: 30 Sekunden; maximales Downloadvolumen pro Seite: 50 MB; maximale Ausgabedateigröße: 50 MB.
Die genauen Limits der einzelnen Tarife finden Sie unter Preise.
Fehlercodes
Fehlerantworten werden immer als JSON zurückgegeben:
{
"error": {
"code": "render_failed",
"message": "target responded with an error status",
"upstream_status": 404,
"request_id": "req_01j…"
}
}| HTTP | code | Bedeutung | Kostenpflichtig |
|---|---|---|---|
| 400 | invalid_params | Parameter fehlt oder liegt außerhalb des zulässigen Bereichs; message nennt den betroffenen Parameter | Nein |
| 400 | html_too_large | html überschreitet 2 MB | Nein |
| 401 | unauthorized | API Key fehlt, ist ungültig oder wurde deaktiviert | Nein |
| 401 | signature_invalid | Signatur stimmt nicht überein (Parameter geändert oder falsches Secret) | Nein |
| 401 | signature_expired | Die signierte URL ist seit dem in expires angegebenen Zeitpunkt abgelaufen | Nein |
| 403 | url_blocked | Zugriff auf die Zieladresse nicht erlaubt (z. B. interne Netzwerkadresse oder localhost) | Nein |
| 408 | render_timeout | Renderdauer überschreitet 30 Sekunden | Nein |
| 422 | render_failed | Zielwebsite gibt 4xx/5xx zurück, DNS-Auflösung fehlgeschlagen oder Zertifikatsfehler; enthält upstream_status | Nein |
| 422 | selector_not_found | Kein Element für selector gefunden oder Zeitüberschreitung bei wait_for_selector | Nein |
| 422 | too_many_redirects | Mehr als 5 Weiterleitungen | Nein |
| 429 | rate_limited | Limit für Anfragen pro Sekunde überschritten; gemäß Retry-After erneut versuchen | Nein |
| 429 | concurrency_exceeded | Limit für gleichzeitige Anfragen überschritten | Nein |
| 429 | quota_exceeded | Monatskontingent aufgebraucht (kostenloser Tarif) | Nein |
| 429 | too_many_batches | Mehr als 5 noch nicht abgeschlossene Stapelaufträge gleichzeitig | Nein |
| 500 | internal | Serverfehler; kontaktieren Sie uns und geben Sie request_id an | Nein |
Asynchrone Stapelverarbeitung
/v1/batch/v1/batch/{id}Übermitteln Sie 1–100 URLs auf einmal. Der Endpunkt gibt sofort eine Auftrags-ID zurück (HTTP 202); die Screenshots werden im Hintergrund nacheinander erstellt. Ideal für mehrere Screenshots, ohne die Verbindung offen halten zu müssen. Sie können den Status regelmäßig abfragen oder webhook_url angeben, um nach Abschluss aller Aufgaben benachrichtigt zu werden. Die Authentifizierung entspricht der synchronen API (nur per Request-Header oder Parameter access_key, keine signierten URLs).
| Parameter | Typ | Standard | Beschreibung |
|---|---|---|---|
| type | enum | screenshot | screenshot (Screenshot) oder pdf. |
| urls | string[] | — | Zu verarbeitende URLs, 1–100. Ist eine davon ungültig, wird die gesamte Anfrage mit 400 abgelehnt. message gibt die Position der ungültigen URL an. |
| options | object | {} | Gemeinsame Parameter für alle URLs, identisch mit denen der synchronen Endpunkte (z. B. full_page, format, viewport_width, cache_ttl). Darf url, html und response_type nicht enthalten. |
| webhook_url | string | — | Optional. URL für die Benachrichtigung nach Abschluss aller Aufgaben, siehe „Webhook bei Abschluss“. |
curl -X POST "https://yhfdghkh6544.com/v1/batch" \
-H "X-Access-Key: $SNAPI_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/snapi"
}'
# Rückgabe: 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/snapi", "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 }
]
}Fortschritt abfragen: Der Auftragsstatus status durchläuft queued (in der Warteschlange), running (in Bearbeitung) und completed (alles abgeschlossen, unabhängig von Erfolg oder Fehler). Jede URL hat den Status pending, running, succeeded oder failed. Bei Erfolg enthält result die Datei-URL, bei einem Fehler enthält error den Fehlercode (identisch mit den synchronen Endpunkten).
curl "https://yhfdghkh6544.com/v1/batch/bat_01j…" -H "X-Access-Key: $SNAPI_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://yhfdghkh6544.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" }
}
]
}- Es gelten dieselben Abrechnungsregeln wie bei den synchronen Endpunkten: pro erfolgreich verarbeiteter URL 1 Kontingenteinheit für einen Screenshot oder 2 für ein PDF. Cache-Treffer und Fehler verbrauchen kein Kontingent.
- Ist das Kontingent beim Einreichen bereits aufgebraucht, wird sofort
quota_exceededzurückgegeben. Wird es während der Verarbeitung aufgebraucht, schlagen die verbleibenden URLs mitquota_exceededfehl. - Pro Konto sind höchstens 5 noch nicht abgeschlossene Stapelaufträge gleichzeitig erlaubt. Bei Überschreitung wird
too_many_batcheszurückgegeben. - Die Gültigkeitsdauer der Ergebnisdateien wird durch
options.cache_ttlbestimmt (standardmäßig 1 Tag). Laden Sie die Dateien rechtzeitig herunter und speichern Sie sie. - In Abfrageergebnissen und Webhooks wird
webhook.urlnur bis zum Pfad angezeigt, ohne Query-String.
Webhook bei Abschluss
Wenn Sie webhook_url angeben, senden wir nach Abschluss des gesamten Auftrags eine POST-Anfrage an diese URL. Der Request-Body ist JSON: { "event": "batch.completed", "batch": { … } }. Dabei entspricht batch genau der Antwort des Abfrage-Endpunkts. Request-Header:
X-Snapi-Signature: t=1760779812,v1=5d3f…:tist der Sendezeitpunkt (Unix-Zeit in Sekunden),v1die SignaturX-Snapi-Event: batch.completed,X-Snapi-Delivery-Attempt: 1(Nummer des Zustellversuchs)
v1 = hex(HMAC-SHA256(secret, t + "." + Unveränderter Request-Body))
secret ist das Signatur-Secret des API Key, mit dem der Auftrag eingereicht wurde (in der Konsole auf der Seite „API Key“ einsehbar).- Antworten Sie innerhalb von 10 Sekunden mit 2xx, andernfalls gilt die Zustellung als fehlgeschlagen. Bei einem Fehler wird die Zustellung nach 10 Sekunden, 1 Minute und 5 Minuten jeweils einmal wiederholt (insgesamt maximal 4 Versuche).
- In seltenen Fällen können Sie für denselben Auftrag mehrere Benachrichtigungen erhalten. Erkennen Sie Duplikate anhand von
batch.id. - Berechnen Sie die Signatur anhand der empfangenen, unveränderten Bytes. Prüfen Sie außerdem, dass
thöchstens wenige Minuten von der aktuellen Zeit abweicht, um Replay-Angriffe zu verhindern. - Die Callback-URL muss eine öffentlich erreichbare http(s)-Adresse sein und darf nicht auf ein internes Netzwerk verweisen.
import crypto from "node:crypto";
// rawBody muss die empfangenen Originalbytes enthalten. Nicht zuerst mit JSON.parse parsen und anschließend erneut serialisieren.
function verifySnapiWebhook(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; // Schutz vor Replay-Angriffen
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);
}
// verifySnapiWebhook(req.rawBody, req.headers["x-snapi-signature"], SNAPI_SECRET)Nutzung abfragen
/v1/usagecurl "https://yhfdghkh6544.com/v1/usage" -H "X-Access-Key: $SNAPI_KEY"
{ "month": "202610", "used": 37, "limit": 100, "remaining": 63, "overage": 0, "resets_at": "2026-11-01T00:00:00Z", ... }Statusprüfung
/v1/healthKeine Authentifizierung erforderlich. Gibt den Knotenstatus und den Status des Browser-Pools zurück (gesamt, belegt, frei).