Website-Screenshot-API#
Der Endpunkt POST /v1/convert/website-to-screenshot ermittelt jede Seite einer Website (per Sitemap-Parsing oder einem vollständigen Breadth-First-Crawl), erstellt einen Full-Page-PNG-Screenshot jeder Seite und bündelt die Ergebnisse in einem einzigen ZIP-Archiv. Jobs laufen immer asynchron: Die API gibt sofort HTTP 202 mit einer batch_id zurück, der Abschluss wird per Batch-Status-Polling, Webhook-Callback oder E-Mail-Benachrichtigung signalisiert, und die Batch-Status-Antwort enthält eine vorsignierte Download-URL für das fertige ZIP. Erfordert einen kostenpflichtigen Plan und einen privaten API-Key.
Endpunkt#
POST /v1/convert/website-to-screenshot
Content-Type: application/json
Ausgabeformat: ZIP-Archiv mit einem PNG-Screenshot pro entdeckter Seite.
Modus: Immer asynchron. Gibt sofort HTTP 202 zurück.
Authentifizierung#
Dieser Endpunkt erfordert einen privaten API-Key. Öffentliche Keys werden für die Website-Erfassung nicht unterstützt.
X-API-Key: sk_your_private_key
Request-Parameter#
Parameter zur Website-Erkennung#
| Parameter | Typ | Erforderlich | Standard | Beschreibung | Plan-Beschränkung |
|---|---|---|---|---|---|
url |
string |
Ja | -- | Die Basis-URL der Website (z. B. https://example.com). Wird als Wurzel für die Seitenermittlung verwendet. |
-- |
crawl_mode |
string |
Nein | "auto" |
Methode zur URL-Ermittlung. Einer von "auto", "sitemap" oder "full". Siehe Crawl-Modi weiter unten. |
Sitemap erfordert Indie+, Full erfordert Studio+ |
include_patterns |
string[] |
Nein | null |
Regex-Muster zum Whitelisten entdeckter URLs. Wird nur im full-Crawl-Modus verwendet. |
-- |
exclude_patterns |
string[] |
Nein | Systemstandard | Regex-Muster zum Blacklisten von URLs. Wird nur im full-Crawl-Modus verwendet. Wenn nicht angegeben, werden integrierte Standardwerte verwendet, die statische Assets, Login-/Admin-/Warenkorb-Seiten und tiefe Paginierung ausschließen. |
-- |
Benachrichtigungsparameter#
| Parameter | Typ | Erforderlich | Standard | Beschreibung | Plan-Beschränkung |
|---|---|---|---|---|---|
output_filename |
string |
Nein | Automatisch generiert | Benutzerdefinierter Basisname für die ZIP-Ausgabedatei. Der Zeitstempel wird automatisch angehängt. | -- |
notification_email |
string |
Nein | E-Mail-Adresse des Projektinhabers | E-Mail-Adresse, die benachrichtigt wird, wenn der Job abgeschlossen ist. | -- |
callback_url |
string |
Nein | -- | Webhook-URL, die bei Abschluss eine POST-Anfrage erhält. | Erfordert Webhook-Zugriff |
Browser- und Rendering-Parameter#
Diese Einstellungen gelten für die Erfassung jeder einzelnen Seite innerhalb der Website.
| Parameter | Typ | Erforderlich | Standard | Beschreibung | Plan-Beschränkung |
|---|---|---|---|---|---|
viewport_width |
integer |
Nein | 1920 |
Browser-Viewport-Breite in Pixeln. Die Screenshot-Breite entspricht diesem Wert. | -- |
viewport_height |
integer |
Nein | 1080 |
Browser-Viewport-Höhe in Pixeln. Wird als Referenz für Rendering- und Viewport-Einheit-Berechnungen verwendet. | -- |
load_media |
boolean |
Nein | true |
Wartet, bis alle Bilder und Videos vollständig geladen sind, bevor die Erfassung erfolgt. | -- |
enable_scroll |
boolean |
Nein | true |
Scrollt jede Seite, um Lazy-Loading-Inhalte auszulösen. | -- |
handle_sticky_header |
boolean |
Nein | true |
Erkennt sticky/fixierte Header und behandelt sie vor der Erfassung. | -- |
handle_cookies |
boolean |
Nein | true |
Schließt Cookie-Consent-Banner automatisch. | -- |
wait_for_images |
boolean |
Nein | true |
Wartet, bis alle <img>-Elemente vollständig geladen sind. |
-- |
wait_for_selector |
string |
Nein | null |
CSS-Selektor, auf den vor der Aufnahme gewartet wird, angewendet auf jede Seite. Gibt 422 zurück, wenn er nicht innerhalb von wait_for_selector_timeout erscheint. Nützlich für SPAs, die Inhalte nach dem Laden hydrieren. |
-- |
wait_for_selector_timeout |
integer |
Nein | 10000 |
Millisekunden, die auf wait_for_selector gewartet wird (maximal 60000). |
-- |
block_ads |
boolean |
Nein | false |
Bricht Anfragen an bekannte Werbe-/Tracker-Domains ab, sodass diese nie geladen, gerendert werden oder die Aufnahme verlangsamen. | -- |
block_media |
boolean |
Nein | false |
Bricht Bild- und Audio-/Videoanfragen vollständig ab, für ein schnelleres, leichteres Rendering. Anders als load_media (das nur das Warten steuert), verhindert dies das Herunterladen von Medien vollständig. |
-- |
Authentifizierung und benutzerdefinierte Anfragen#
| Parameter | Typ | Erforderlich | Standard | Beschreibung | Plan-Beschränkung |
|---|---|---|---|---|---|
auth |
object |
Nein | null |
HTTP-Basic-Auth-Anmeldedaten, die auf jede Seite angewendet werden. Format: {"username": "...", "password": "..."}. |
Erfordert Basic-Auth-Zugriff |
cookies |
array |
Nein | null |
Array von Cookie-Objekten, die vor jedem Seitenaufruf injiziert werden. Maximal 50 Cookies. | Erfordert Basic-Auth-Zugriff |
headers |
object |
Nein | null |
Benutzerdefinierte HTTP-Header, die mit jeder Anfrage gesendet werden. Maximal 20 Header. | Erfordert Basic-Auth-Zugriff |
single_page und pdf_options gelten nicht für Screenshots. Jede Seite wird immer als einzelnes Full-Page-PNG-Bild erfasst.
Crawl-Modi#
"auto" (Standard)#
Verwendet den höchsten Crawl-Modus, den Ihr Plan zulässt. Wenn Ihr Plan vollständiges Crawling unterstützt, wird ein Full-Crawl ausgeführt. Wenn Ihr Plan nur Sitemap unterstützt, wird die Sitemap-Ermittlung ausgeführt.
"sitemap"#
Ermittelt Seiten durch Parsen der sitemap.xml der Website:
- Ruft
{base_url}/sitemap.xmlab (30-Sekunden-Timeout) - Wenn das Root-Element
<sitemapindex>ist, werden alle untergeordneten Sitemaps rekursiv abgerufen - Extrahiert alle
<url><loc>-Einträge aus<urlset>-Elementen - Gibt die vollständige Liste der entdeckten URLs zurück
Gibt einen Fehler zurück, wenn die Sitemap fehlt, einen Nicht-200-Status zurückgibt, ungültiges XML enthält oder keine URLs hat.
"full"#
Führt einen umfassenden zweiphasigen Crawl durch:
Phase 1 -- Seed-Ermittlung:
- Parst
robots.txtnach Sitemap-Direktiven und Crawl-Regeln - Prüft Standard-Sitemap-Pfade (
/sitemap.xml,/wp-sitemap.xml,/sitemap_index.xmlusw.) - Ermittelt RSS-/Atom-Feeds aus
<link>-Tags und gängigen Feed-Pfaden - Extrahiert Seed-URLs aus allen entdeckten Quellen
Phase 2 -- Breadth-First-Link-Crawl:
- Startet bei der Basis-URL plus allen Seed-URLs
- Besucht jede Seite und reiht Links derselben Domain ein
- Wendet
include_patternsundexclude_patternsan, um Links zu filtern - Berücksichtigt
robots.txt-Regeln - Erkennt und vermeidet unendliche URL-Fallen (Kalenderseiten, facettierte Filter usw.)
- Dedupliziert URLs durch Normalisierung von Schema, Host und Query-Parametern sowie Entfernen von Tracking-Parametern (
utm_*,fbclid,gclidusw.)
Standard-Ausschlussmuster (wenn exclude_patterns nicht angegeben wird):
- Statische Assets:
*.pdf,*.zip,*.jpg,*.png,*.gif,*.svg,*.css,*.js,*.xml,*.json,*.mp4,*.webm,*.woff,*.woff2 - Geschützte Pfade:
/login,/admin,/cart,/checkout - Tiefe Paginierung: URLs mit
page=-Parametern über 3 Stellen
Antwort#
202 Accepted (sofort)#
{
"status": "processing",
"batch_id": "550e8400-e29b-41d4-a716-446655440000",
"url_count": 42,
"total_discovered": 42,
"discovery_method": "sitemap",
"output_format": "zip"
}
| Feld | Beschreibung |
|---|---|
batch_id |
UUID zur Nachverfolgung des Jobs per Batch-Status-Polling oder Webhook. |
url_count |
Anzahl der Seiten, die erfasst werden. |
total_discovered |
Gesamtzahl der vom Crawl entdeckten Seiten. |
discovery_method |
"sitemap" oder "full_crawl", abhängig vom effektiven Crawl-Modus. |
Batch-Status-Polling#
Fragen Sie mit der batch_id aus der 202-Antwort ab:
GET /v1/convert/batch/{batch_id}
X-API-Key: sk_your_private_key
Gibt den Gesamtstatus, den Status pro URL und bei Abschluss eine vorsignierte Download-URL für das ZIP zurück. Das vollständige Antwortschema finden Sie unter Batch-Status-Polling.
Webhook-Callback-Payload#
Wenn callback_url angegeben ist, sendet EnConvert bei Abschluss eine POST-Anfrage:
{
"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"}
]
}
E-Mail-Benachrichtigung#
Bei Abschluss des Jobs wird eine Abschluss-E-Mail an notification_email gesendet (standardmäßig an die E-Mail-Adresse des Projektinhabers), unabhängig von Erfolg oder Fehlschlag.
Plan-Beschränkungen#
| Funktion | Founding | Indie | Studio | Enterprise |
|---|---|---|---|---|
| Website-Erfassung | Nein | Ja | Ja | Ja |
| Sitemap-Crawl-Modus | Nein | Ja | Ja | Ja |
| Full-Crawl-Modus | Nein | Nein | Ja | Ja |
| Webhook-Callbacks | Nein | Nein | Ja | Ja |
| HTTP Basic Auth | Nein | Ja | Ja | Ja |
| Cookie-Injection | Nein | Ja | Ja | Ja |
| Benutzerdefinierte Header | Nein | Ja | Ja | Ja |
| Batch-Größenlimit | 0 | Planabhängig | Planabhängig | Unbegrenzt |
| Monatliche Konvertierungen | 100 | Planabhängig | Planabhängig | Unbegrenzt |
403 Forbidden zurück.
Codebeispiele#
Python (privater Key)#
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 (privater Key)#
$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 (privater Key)#
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 (privater Key)#
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))
}
Mit Webhook-Callback#
{
"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\\/.*"]
}
Mit Authentifizierung (passwortgeschützte Website)#
{
"url": "https://staging.example.com",
"crawl_mode": "sitemap",
"auth": {
"username": "admin",
"password": "staging-password"
},
"cookies": [
{"name": "session_token", "value": "abc123", "domain": "staging.example.com"}
]
}
Fehlerantworten#
| Status | Bedingung |
|---|---|
400 Bad Request |
Fehlender oder leerer url-Parameter |
400 Bad Request |
Keine URLs in der Sitemap gefunden |
400 Bad Request |
Timeout beim Abrufen der Sitemap (30-Sekunden-Limit) |
400 Bad Request |
Nicht-200-Antwort von der Sitemap-URL |
400 Bad Request |
Ungültiges XML in der Sitemap |
400 Bad Request |
Nicht erkanntes Sitemap-Format |
400 Bad Request |
Keine Seiten entdeckt (Full-Crawl fand null URLs) |
400 Bad Request |
Ungültige Struktur von auth, cookies oder headers |
402 Payment Required |
Monatliches Ops-Kontingent durch die Anzahl entdeckter Seiten überschritten |
402 Payment Required |
Speicherlimit erreicht |
403 Forbidden |
Website-Crawling im aktuellen Plan nicht verfügbar (Founding-Plan) |
403 Forbidden |
Full-Crawl-Modus erfordert den Studio-Plan oder höher |
403 Forbidden |
Anzahl entdeckter Seiten überschreitet das Batch-Größenlimit |
403 Forbidden |
Feature im Plan nicht verfügbar (Webhook, Basic Auth) |
500 Internal Server Error |
Crawl- oder Erfassungsfehler |
Limits#
| Limit | Wert |
|---|---|
| Sitemap-Abruf-Timeout | 30 Sekunden |
| Globales Crawl-Timeout (Full-Modus) | 10 Minuten |
| Maximale Crawl-Tiefe (Full-Modus) | 10 Ebenen |
| Crawl-Timeout pro Seite (Full-Modus) | 30 Sekunden |
| Crawler-Speicherlimit | 512 MB |
| Schwellenwert für Endlos-Fallen | 20 URLs pro URL-Muster |
| Robots.txt-Abruf-Timeout | 10 Sekunden |
| Maximale Seiten pro Crawl | Batch-Größenlimit des Plans |
| Maximale Cookies pro Anfrage | 50 |
| Maximale benutzerdefinierte Header pro Anfrage | 20 |
| Webhook-Zustellungs-Timeout | 30 Sekunden |
| Monatliche Konvertierungen | Planabhängig |
| Dateiaufbewahrung | Planabhängig |
Häufig gestellte Fragen#
Wie screenshotte ich jede Seite einer Website mit einer API?#
Senden Sie eine POST-Anfrage an /v1/convert/website-to-screenshot mit der Basis-url der Seite und Ihrem privaten Key im X-API-Key-Header. Die API ermittelt jede Seite (Sitemap oder Full-Crawl), erstellt von jeder einen Full-Page-PNG-Screenshot, bündelt sie in einem ZIP-Archiv und gibt HTTP 202 mit einer batch_id zurück, die Sie für den Download-Link abfragen können.
Kann ich die Größe oder das Format der Screenshots steuern?#
Die Screenshot-Breite entspricht viewport_width (Standard 1920), und viewport_height wird als Rendering-Referenz verwendet. Jede Seite wird immer als einzelnes Full-Page-PNG erfasst. Die Parameter single_page und pdf_options gelten nicht für Screenshots.
Wie lade ich die Screenshots herunter, wenn der Job abgeschlossen ist?#
Fragen Sie GET /v1/convert/batch/{batch_id} mit Ihrem privaten Key ab, um den Gesamtstatus, den Status pro URL und eine vorsignierte ZIP-Download-URL zu erhalten, oder übergeben Sie eine callback_url, um bei Abschluss einen Webhook-POST zu erhalten. Zusätzlich wird eine Abschluss-E-Mail an notification_email gesendet (standardmäßig an den Projektinhaber).
Kann ich eine passwortgeschützte Website oder eine Staging-Website screenshotten?#
Ja, auf Plänen mit Basic-Auth-Zugriff: Übergeben Sie auth mit username und password für HTTP Basic Auth, die auf jede Seite angewendet wird, injizieren Sie bis zu 50 Sitzungs-cookies oder senden Sie bis zu 20 benutzerdefinierte headers.
Warum gibt der Website-to-Screenshot-Endpunkt 403 Forbidden zurück?#
Die häufigsten Ursachen: Die Website-Erfassung ist im Founding-Plan nicht verfügbar, crawl_mode: "full" erfordert Studio oder höher, die Anzahl entdeckter Seiten überschreitet das Batch-Größenlimit Ihres Plans, oder ein angefordertes Feature (Webhook, Basic Auth) ist in Ihrem Plan nicht enthalten.