---
seo_title: Website-Screenshot-API | Ganzseitige URL-Erfassung | EnConvert
meta_desc: Erfasst Ganzseiten-Screenshots von Websites als PNG über POST /v1/convert/url-to-screenshot – mit Cookie-Banner-Handling, Lazy-Loading und presigned URLs.
keywords: website screenshot api, screenshot von webseite erstellen, ganzseitigen screenshot per api, webseite als png speichern, url zu screenshot api, puppeteer alternative screenshot api, webseiten automatisch screenshotten, screenshot api für entwickler
---

# Website-Screenshot-API

Der Endpunkt `POST /v1/convert/url-to-screenshot` erfasst einen Ganzseiten-Screenshot einer beliebigen öffentlich zugänglichen URL als hochwertiges PNG-Bild. Er behandelt automatisch Cookie-Banner, Modals, Lazy-Loading-Inhalte, scroll-getriggerte Animationen und Sticky-Header, um eine saubere, präzise Erfassung zu erzeugen. Führe ihn synchron aus, um eine presigned Download-URL oder rohe PNG-Bytes zu erhalten, oder nutze den asynchronen Modus, um mehrere URLs in einem Batch als Screenshot zu erfassen.

---

## Endpunkt

```
POST /v1/convert/url-to-screenshot
```

**Content-Type:** `application/json`

**Ausgabeformat:** PNG (immer). Das Ausgabeformat ist nicht konfigurierbar. Alle Screenshots werden als ganzseitige PNG-Bilder erfasst.

---

## Authentifizierung

Dieser Endpunkt unterstützt sowohl die Authentifizierung mit privatem als auch mit öffentlichem Schlüssel.

### Privater Schlüssel

Übergib deinen geheimen Schlüssel im `X-API-Key`-Header. Nutze dies für Server-zu-Server-Aufrufe, bei denen der Schlüssel niemals gegenüber dem Client offengelegt wird.

```
X-API-Key: sk_your_private_key
```

### Öffentlicher Schlüssel mit JWT

Erzeuge für die clientseitige Nutzung zunächst mit deinem öffentlichen Schlüssel ein JWT-Token und übergib es anschließend als Bearer-Token.

**Schritt 1 -- Token abrufen:**

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

**Schritt 2 -- Token verwenden:**

```
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
```

<div class="alert alert-info">
<strong>Hinweis:</strong> Anfragen mit öffentlichem Schlüssel sind auf eine einzelne URL, den synchronen Modus und den direkten Download beschränkt. Asynchroner Modus, Batch-Verarbeitung, Webhooks und Benachrichtigungs-E-Mails stehen bei öffentlichen Schlüsseln nicht zur Verfügung.
</div>

---

## Anfrageparameter

### Top-Level-Parameter

| Parameter | Typ | Erforderlich | Standard | Beschreibung | Plan-Beschränkung |
|-----------|------|----------|---------|-------------|-------------|
| `url` | `string` oder `string[]` | Ja | -- | Ein einzelner URL-String oder ein Array von URLs, die erfasst werden sollen. Mehrere URLs erfordern den asynchronen Modus. | -- |
| `async_mode` | `boolean` | Nein | `false` | Führt die Erfassung asynchron aus. Liefert sofort eine `batch_id` zurück. Erforderlich für Batch (mehrere URLs). | Erfordert Async-Zugriff |
| `direct_download` | `boolean` | Nein | `false` | Liefert rohe PNG-Bytes im Response-Body statt einer JSON-Antwort mit presigned URL. Wird für öffentliche Schlüssel zwangsweise auf `true` gesetzt. Nicht kompatibel mit `async_mode` und mehreren URLs. | -- |
| `output_format` | `boolean` | Nein | `false` | Bündelt bei `true` mit mehreren URLs alle Ausgabe-PNGs in ein einziges ZIP-Archiv. Erfordert mehrere URLs. | Erfordert Zugriff auf ZIP-Ausgabe |
| `output_filename` | `string` | Nein | Automatisch generiert | Benutzerdefinierter Dateiname für die Ausgabedatei. Die Erweiterung `.png` wird automatisch angehängt. Standardformat: `{domain}_{timestamp}.png`. | -- |
| `job_id` | `string` | Nein | -- | Vom Client bereitgestellte Job-ID zur Timeout-Wiederherstellung. **Nur öffentliche Schlüssel.** Wenn eine synchrone Konvertierung die Timeout-Limits des Reverse-Proxys überschreitet, kann der Client das Ergebnis über `GET /v1/convert/status/{job_id}` abfragen. Wird bei privaten Schlüsseln ignoriert. | -- |
| `notification_email` | `string` | Nein | E-Mail-Adresse des Projektinhabers | E-Mail-Adresse, die benachrichtigt wird, wenn ein asynchroner Job abgeschlossen ist. Nur private Schlüssel. | -- |
| `callback_url` | `string` | Nein | -- | Webhook-URL, die bei Abschluss der Erfassung eine POST-Anfrage erhält. Nur private Schlüssel. | Erfordert Webhook-Zugriff |

### Browser- und Rendering-Parameter

| Parameter | Typ | Erforderlich | Standard | Beschreibung | Plan-Beschränkung |
|-----------|------|----------|---------|-------------|-------------|
| `viewport_width` | `integer` | Nein | `1920` | Breite des Browser-Viewports in Pixeln. Die Breite des Screenshots entspricht diesem Wert. | -- |
| `viewport_height` | `integer` | Nein | `1080` | Höhe des Browser-Viewports in Pixeln. Dient als Referenz für das Rendering und die Berechnung der Viewport-Einheiten. Die tatsächliche Höhe des Screenshots wird durch die vollständige Seiteninhaltshöhe bestimmt. | -- |
| `load_media` | `boolean` | Nein | `true` | Wartet vor der Erfassung, bis alle Bilder und Videos vollständig geladen sind. Bei `false` ist die Erfassung schneller, Medien können jedoch als Platzhalter erscheinen. | -- |
| `enable_scroll` | `boolean` | Nein | `true` | Scrollt die Seite von oben nach unten, um Lazy-Loading-Inhalte auszulösen (auf IntersectionObserver basierende Loader). | -- |
| `handle_sticky_header` | `boolean` | Nein | `true` | Erkennt sticky/fixierte Header und scrollt vor der Erfassung nach oben, damit der Header korrekt am oberen Rand des Screenshots gerendert wird. | -- |
| `handle_cookies` | `boolean` | Nein | `true` | Schließt Cookie-Consent-Banner automatisch (OneTrust, Cookiebot, Didomi, Usercentrics und generische Banner). | -- |
| `wait_for_images` | `boolean` | Nein | `true` | Wartet, bis alle `<img>`-Elemente vollständig geladen sind (5 Sekunden Timeout pro Bild). | -- |
| `wait_for_selector` | `string` | Nein | `null` | CSS-Selektor, auf den vor der Aufnahme gewartet wird. 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 & benutzerdefinierte Anfragen

| Parameter | Typ | Erforderlich | Standard | Beschreibung | Plan-Beschränkung |
|-----------|------|----------|---------|-------------|-------------|
| `auth` | `object` | Nein | `null` | HTTP-Basic-Auth-Zugangsdaten für die Ziel-URL. Format: `{"username": "...", "password": "..."}`. Kann nicht zusammen mit einem benutzerdefinierten `Authorization`-Header verwendet werden. | Erfordert Basic-Auth-Zugriff |
| `cookies` | `array` | Nein | `null` | Array von Cookie-Objekten, die vor der Navigation eingeschleust werden. Maximal 50 Cookies. Jedes Cookie benötigt `name`, `value` sowie entweder `domain` oder `url`. | Erfordert Basic-Auth-Zugriff |
| `headers` | `object` | Nein | `null` | Dictionary mit benutzerdefinierten HTTP-Headern, die mit jeder Anfrage an die Ziel-URL gesendet werden. Maximal 20 Header. Gesperrte Header: `host`, `content-length`, `transfer-encoding`, `connection`, `upgrade`, `te`, `trailer`. | Erfordert Basic-Auth-Zugriff |

<div class="alert alert-warning">
<strong>Nicht unterstützt:</strong> Die Parameter <code>single_page</code> und <code>pdf_options</code> des Endpunkts <a href="/de/docs/endpoints/convert/web-pages/url-to-pdf">url-to-pdf</a> sind für Screenshots nicht anwendbar. Screenshots erfassen immer die gesamte Seite als ein einziges durchgehendes Bild.
</div>

---

## Cookie-Objekt-Schema

Jeder Eintrag im Array `cookies` muss folgender Struktur entsprechen:

| Feld | Typ | Erforderlich | Standard | Beschreibung |
|-------|------|----------|---------|-------------|
| `name` | `string` | Ja | -- | Cookie-Name. |
| `value` | `string` | Ja | -- | Cookie-Wert. |
| `domain` | `string` | Bedingt | -- | Cookie-Domain. Entweder `domain` oder `url` muss angegeben werden. |
| `url` | `string` | Bedingt | -- | URL, mit der das Cookie verknüpft wird. Entweder `domain` oder `url` muss angegeben werden. |
| `path` | `string` | Nein | `"/"` | Cookie-Pfad. Standardmäßig `"/"`, wenn `domain` gesetzt ist. |

---

## Antwort

### Synchron mit direktem Download (`direct_download=true`)

**Privater Schlüssel** -- liefert rohe PNG-Bytes zurück:

```
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)
```

**Öffentlicher Schlüssel** -- liefert JSON mit einer presigned URL zurück:

```json
{
    "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"
}
```

### Synchron ohne direkten Download (`direct_download=false`)

Nur mit privaten Schlüsseln verfügbar.

```json
{
    "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
}
```

### Asynchroner Modus

Liefert sofort eine `batch_id` zur Nachverfolgung zurück.

```
HTTP 202 Accepted
```

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

Bei `output_format=true` (ZIP-Bündelung):

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

### Job-Status-Abfrage (nur öffentliche Schlüssel)

Für die Timeout-Wiederherstellung bei öffentlichen Schlüsseln:

```
GET /v1/convert/status/{job_id}
Authorization: Bearer <jwt_token>
```

| Status | Antwort |
|--------|----------|
| In Bearbeitung | `{"status": "processing"}` |
| Erfolg | `{"status": "success", "presigned_url": "...", "object_key": "..."}` |
| Fehlgeschlagen | `{"status": "failed", "error": "..."}` |

### Batch-Status-Abfrage (nur private Schlüssel)

Frage bei asynchronen Batch-Jobs mit der `batch_id` aus der 202-Antwort ab:

```
GET /v1/convert/batch/{batch_id}
X-API-Key: sk_your_private_key
```

Liefert den Gesamtstatus, Status pro URL sowie presigned Download-URLs zurück. Das vollständige Antwortschema findest du unter [Batch-Status-Abfrage](/de/docs/endpoints/convert/web-pages/url-to-pdf.md#batch-status-polling-private-keys-only).

### Webhook-Callback-Payload

Wenn eine `callback_url` angegeben ist, sendet EnConvert nach Abschluss eine POST-Anfrage an diese URL.

**Einzelner URL-Job:**

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

**Batch-Job:**

```json
{
    "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}
    ]
}
```

---

## Funktionen

### Ganzseitige Erfassung

Jeder Screenshot erfasst den **gesamten Seiteninhalt**, nicht nur den sichtbaren Viewport. Der Converter:

1. Rendert die Seite mit der angegebenen `viewport_width` und `viewport_height`
2. Scrollt durch die Seite, um sämtliche Lazy-Loading-Inhalte auszulösen
3. Berechnet die tatsächliche Inhaltshöhe mithilfe eines DOM-Tree-Walkers, der die maximale untere Position aller sichtbaren Elemente misst
4. Passt den Viewport an, sodass er die vollständige Inhaltshöhe umfasst
5. Erfasst den Screenshot mit `full_page=true`

Das Ergebnis ist ein einzelnes, hohes PNG-Bild der kompletten Seite.

### Klarer Erfassungsmodus

EnConvert behandelt automatisch gängige Hindernisse auf Webseiten, um saubere Screenshots zu erzeugen:

- **Cookie-Consent-Banner** -- Schließt automatisch Banner von OneTrust, Cookiebot, Didomi, Usercentrics und generischen Implementierungen. Funktioniert sowohl auf der Hauptseite als auch in iframes.
- **Schließen von Modals und Popups** -- Schließt Overlays mit mehreren Strategien: Escape-Taste, ARIA-Schließen-Buttons, klassenbasierte Schließen-Buttons (`"Close"`, `"Not now"`, `"No thanks"`, `"Skip"`) und rollenbasierte Dialog-Buttons. Entfernt nach dem Schließen verbleibende Blur-, Backdrop- und Inert-Effekte.
- **Aufdecken von Scroll-Animationen** -- Erzwingt die Sichtbarkeit von Elementen, die durch scroll-getriggerte Animationsbibliotheken wie WOW.js, AOS, ScrollReveal, GSAP ScrollTrigger sowie generische Animationsklassen (`.fadeIn`, `.slideIn` usw.) verborgen werden. Deckt außerdem alle Swiper-Slides auf.
- **Dropdown-Bereinigung** -- Schließt alle geöffneten Dropdowns, wandelt Navigations-Button-Elemente in echte Anchor-Links um, damit sie visuell sauber bleiben, blendet `role="menu"`-Elemente aus und positioniert fixierte Header auf statische Positionierung um.

### Normalisierung von Viewport-Einheiten

Screenshots erfordern eine besondere Behandlung von CSS-Viewport-Einheiten (`vh`, `svh`, `lvh`, `dvh`), da der Viewport auf die volle Seitenhöhe angepasst wird. Ohne Normalisierung würden mit Viewport-Einheiten dimensionierte Elemente auf enorme Größen anwachsen. Der Converter:

- Wandelt alle viewport-relativen Einheiten anhand der ursprünglichen Viewport-Höhe in feste Pixelwerte um
- Begrenzt ungewöhnlich hohe Bilder und Videos auf das 1,5-fache der ursprünglichen Viewport-Höhe
- Behandelt Elementor-spezifische Eigenheiten bei der Höhe (Flex-Container, Motion-Effekte, Hintergrund-Container)
- Erhält die Videodimensionen während des gesamten Normalisierungsprozesses

### HTTP Basic Auth

Übergib `auth` mit `username` und `password`, um Seiten hinter HTTP Basic Authentication zu erfassen.

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

### Cookie-Injection

Schleuse bis zu 50 Cookies ein, bevor die Seite lädt. Nützlich, um Seiten zu erfassen, die eine aktive Sitzung erfordern.

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

### Benutzerdefinierte Header

Sende bis zu 20 benutzerdefinierte HTTP-Header mit jeder Anfrage an die Zielseite.

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

### Lazy-Loading von Bildern

Wenn `load_media` und `enable_scroll` aktiviert sind (beide standardmäßig `true`), scrollt der Converter die Seite langsam (120px alle 90ms), um Lazy-Loader auszulösen, und wartet anschließend mit einer 500ms langen Layout-Stabilisierungsphase, bis alle Bilder vollständig geladen sind.

Setze `load_media=false` für eine schnellere Erfassung. Der Converter nutzt dann schnelles Scrollen (300px alle 30ms) mit einer kürzeren 100ms-Stabilisierung, wobei Medien jedoch als Platzhalter erscheinen können.

### Behandlung von Sticky-Headern

Wenn aktiviert (Standard `true`), erkennt der Converter fixierte und sticky positionierte Elemente, die wie Header wirken, positioniert sie für einen sauberen Screenshot auf statische Positionierung um und scrollt vor der Erfassung an den Seitenanfang.

### Weitere Rendering-Funktionen

- **Screen-Media-Emulation** -- Die Seite wird mit dem CSS-Medientyp `screen` gerendert (nicht `print`), sodass der Screenshot dem entspricht, was Nutzer in ihrem Browser sehen.
- **Stealth-Modus** -- Nutzt Browser-Fingerprint-Maskierung, um Bot-Erkennung auf geschützten Seiten zu vermeiden.
- **Popup-Interception** -- Schließt automatisch alle neuen Browser-Tabs oder Popups, die von der Seite ausgelöst werden.
- **CSP-Bypass** -- Behandelt Content-Security-Policy- und Trusted-Types-Beschränkungen, die die Manipulation der Seite andernfalls blockieren würden.
- **Shadow-Erhaltung** -- Elemente mit `box-shadow` und `text-shadow` werden markiert, damit Schatten im Screenshot korrekt gerendert werden.

---

## Einschränkungen nach Plan

| Feature | Founding | Indie | Studio | Enterprise |
|---------|------|---------|-----|------------|
| Basis-Erfassung (einzelne URL, synchron) | Ja | Ja | Ja | Ja |
| Viewport-Größe | Ja | Ja | Ja | Ja |
| Asynchroner Modus | Nein | Ja | Ja | Ja |
| Batch-Verarbeitung (mehrere URLs) | Nein | Ja | Ja | Ja |
| ZIP-Bündelung der Ausgabe | 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 |
| Monatliche Konvertierungen | 100 | Planabhängig | Planabhängig | Unbegrenzt |
| Limit für Batch-Größe | 0 | Planabhängig | Planabhängig | Unbegrenzt |
| Aufbewahrungsdauer der Dateien | 1 Stunde | Planabhängig | Planabhängig | Planabhängig |

---

## Asynchroner Modus

Der asynchrone Modus ist nützlich für lang laufende Erfassungen oder wenn mehrere URLs als Screenshot erfasst werden sollen.

### So funktioniert es

1. Sende eine Anfrage mit `async_mode=true` (oder übergib mehrere URLs, wodurch Async automatisch aktiviert wird).
2. Die API liefert sofort HTTP 202 mit einer `batch_id` und `url_count` zurück.
3. Jede URL wird im Hintergrund erfasst, in den Storage hochgeladen und einzeln nachverfolgt.
4. Überwache den Abschluss per **Batch-Status-Abfrage**, **E-Mail-Benachrichtigung** oder **Webhook-Callback**.

### E-Mail-Benachrichtigung

Standardmäßig wird eine Abschluss-E-Mail an die E-Mail-Adresse des Projektinhabers gesendet. Überschreibe dies mit `notification_email`:

```json
{
    "url": ["https://example.com/page1", "https://example.com/page2"],
    "async_mode": true,
    "notification_email": "team@example.com"
}
```

### Webhook-Callback

Gib eine `callback_url` an, um bei Abschluss automatisch eine POST-Benachrichtigung zu erhalten:

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

---

## Batch- und Massenverarbeitung

Erfasse mehrere URLs in einer einzigen Anfrage. Erfordert den asynchronen Modus und einen privaten Schlüssel.

### Einzelne Ausgabe (Standard)

Jede URL erzeugt eine eigene PNG-Datei:

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

### ZIP-Bündel-Ausgabe

Bündle alle Screenshots in einem einzigen ZIP-Archiv:

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

---

## Codebeispiele

### Python (privater Schlüssel)

```python
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 (privater Schlüssel)

```php
$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 (privater Schlüssel)

```javascript
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 (privater Schlüssel)

```go
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 (öffentlicher Schlüssel)

```javascript
// 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 (öffentlicher Schlüssel)

```jsx
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;
```

---

## Fehlerantworten

| Status | Bedingung |
|--------|-----------|
| `400 Bad Request` | Fehlender oder leerer Parameter `url` |
| `400 Bad Request` | `output_format=true` bei einer einzelnen URL (erfordert mehrere URLs) |
| `400 Bad Request` | `direct_download=true` bei mehreren URLs |
| `400 Bad Request` | `direct_download=true` zusammen mit `async_mode=true` |
| `400 Bad Request` | Ungültiges `auth`-Objekt (fehlender `username` oder `password`) |
| `400 Bad Request` | Ungültige `cookies` (kein Array, mehr als 50 Einträge, fehlende Pflichtfelder) |
| `400 Bad Request` | Ungültige `headers` (kein Objekt, mehr als 20 Einträge, gesperrte Header-Namen, nicht-String-Werte) |
| `400 Bad Request` | Widerspruch zwischen `auth` und dem benutzerdefinierten `Authorization`-Header |
| `400 Bad Request` | Öffentlicher Schlüssel mit mehreren URLs |
| `401 Unauthorized` | Fehlender oder ungültiger API-Key / JWT-Token |
| `402 Payment Required` | Monatliches Ops-Kontingent aufgebraucht |
| `402 Payment Required` | Batch würde das verbleibende monatliche Ops-Kontingent überschreiten |
| `402 Payment Required` | Speicherlimit erreicht |
| `403 Forbidden` | Endpoint nicht in den erlaubten Endpoints des API-Keys |
| `403 Forbidden` | Feature im aktuellen Plan nicht verfügbar (Async, Webhook, ZIP, Basic Auth) |
| `403 Forbidden` | Batch-Größe überschreitet das Batch-Limit des Plans |
| `404 Not Found` | Job-ID nicht gefunden (bei Status-Abfrage) |
| `500 Internal Server Error` | Erfassung fehlgeschlagen (Browser-Absturz, Rendering-Fehler) |

---

## Limits

| Limit | Wert |
|-------|-------|
| Timeout für Seitennavigation | 60 Sekunden |
| Lade-Timeout pro Bild | 5 Sekunden |
| Timeout zum Schließen des Cookie-Banners | 3 Sekunden |
| Maximale Cookies pro Anfrage | 50 |
| Maximale benutzerdefinierte Header pro Anfrage | 20 |
| Monatliche Operationen | Planabhängig (Founding: 500) |
| Batch-Größe | Planabhängig (Founding: deaktiviert) |
| Aufbewahrungsdauer | Planabhängig (Founding: 1 Stunde) |
| Timeout für Webhook-Zustellung | 30 Sekunden |

---

## Häufig gestellte Fragen

### Wie erstelle ich per API einen Ganzseiten-Screenshot einer Website?

Sende eine `POST`-Anfrage an `/v1/convert/url-to-screenshot` mit einem JSON-Body, der `url` enthält, und authentifiziere dich mit deinem privaten Schlüssel im `X-API-Key`-Header (oder einem JWT-Bearer-Token aus einem öffentlichen Schlüssel). Jede Erfassung umfasst den gesamten Seiteninhalt, nicht nur den sichtbaren Viewport. Der Converter passt den Viewport auf die volle Inhaltshöhe an und erfasst mit `full_page=true`.

### Kann ich das Ausgabeformat des Screenshots auf JPEG oder WebP ändern?

Nein. Das Ausgabeformat ist nicht konfigurierbar. Alle Screenshots werden als ganzseitige PNG-Bilder erfasst.

### Wie steuere ich die Breite und Größe des Screenshots?

Setze `viewport_width` (Standard `1920`). Die Breite des Screenshots entspricht diesem Wert. Die Höhe des Screenshots wird durch die vollständige Seiteninhaltshöhe bestimmt, wobei `viewport_height` (Standard `1080`) als Referenz für das Rendering und die Berechnung der Viewport-Einheiten dient.

### Kann ich eine Seite hinter einem Login als Screenshot erfassen?

Ja. Verwende den Parameter `auth` für HTTP Basic Auth, schleuse mit `cookies` bis zu 50 Sitzungs-Cookies ein oder sende mit `headers` bis zu 20 benutzerdefinierte HTTP-Header. Diese Optionen erfordern Basic-Auth-Zugriff in deinem Plan.

### Wie entfernt die API Cookie-Banner und Popups aus Screenshots?

Mit aktiviertem `handle_cookies` (Standard `true`) schließt der Converter automatisch Consent-Banner von OneTrust, Cookiebot, Didomi, Usercentrics und generischen Implementierungen, sowohl auf der Hauptseite als auch in iframes. Modals und Popups werden über die Escape-Taste, ARIA-Schließen-Buttons, klassenbasierte Schließen-Buttons und rollenbasierte Dialog-Buttons geschlossen, wobei verbleibende Blur- und Backdrop-Effekte entfernt werden.
