API Site Web vers PDF#

L'endpoint POST /v1/convert/website-to-pdf explore un site web entier — via l'analyse du sitemap ou un crawl complet en largeur d'abord — convertit chaque page découverte en un PDF haute fidélité, et regroupe les résultats dans une seule archive ZIP. Les jobs s'exécutent toujours de façon asynchrone : l'API renvoie immédiatement HTTP 202 avec un batch_id, la fin du job est signalée via le polling du statut du batch, un callback webhook, ou une notification par e-mail, et la réponse de statut du batch inclut une URL de téléchargement présignée pour le ZIP terminé. Nécessite un forfait payant et une clé API privée.


Endpoint#

POST /v1/convert/website-to-pdf

Content-Type : application/json

Format de sortie : archive ZIP contenant un PDF par page découverte.

Mode : toujours asynchrone. Renvoie immédiatement HTTP 202.


Authentification#

Cet endpoint nécessite une clé API privée. Les clés publiques ne sont pas prises en charge pour la capture de site web.

X-API-Key: sk_live_your_private_key

Paramètres de la requête#

Paramètres de découverte du site web#

Paramètre Type Requis Défaut Description Restriction de forfait
url string Oui -- L'URL de base du site web (par ex. https://example.com). Utilisée comme racine pour la découverte des pages. --
crawl_mode string Non "auto" Méthode de découverte des URL. L'une de "auto", "sitemap" ou "full". Voir Modes de crawl ci-dessous. Sitemap nécessite Starter+, Full nécessite Pro+
include_patterns string[] Non null Motifs regex pour mettre en liste blanche les URL découvertes. Utilisé uniquement en mode de crawl full. --
exclude_patterns string[] Non Valeurs par défaut du système Motifs regex pour mettre en liste noire les URL. Utilisé uniquement en mode de crawl full. Lorsqu'omis, utilise des valeurs par défaut intégrées qui excluent les ressources statiques, les pages de connexion/admin/panier, et la pagination profonde. --

Paramètres de notification#

Paramètre Type Requis Défaut Description Restriction de forfait
output_filename string Non Généré automatiquement Nom de base personnalisé pour le fichier ZIP de sortie. Un horodatage est ajouté automatiquement. --
notification_email string Non E-mail du propriétaire du projet Adresse e-mail à notifier lorsque le job se termine. --
callback_url string Non -- URL de webhook recevant une requête POST à la fin. Nécessite l'accès aux webhooks

Paramètres du navigateur et du rendu#

Ces réglages s'appliquent à la conversion de chaque page individuelle au sein du site web.

Paramètre Type Requis Défaut Description Restriction de forfait
viewport_width integer Non 1920 Largeur du viewport du navigateur en pixels. --
viewport_height integer Non 1080 Hauteur du viewport du navigateur en pixels. --
single_page boolean Non true true restitue chaque page comme une seule page PDF continue. false produit une sortie paginée utilisant la taille de page de pdf_options. --
load_media boolean Non true Attend que toutes les images et vidéos soient entièrement chargées avant la conversion. --
enable_scroll boolean Non true Fait défiler chaque page pour déclencher le contenu à chargement différé. --
handle_sticky_header boolean Non true Détecte les en-têtes collants/fixes et les gère avant la capture. --
handle_cookies boolean Non true Ferme automatiquement les bannières de consentement aux cookies. --
wait_for_images boolean Non true Attend que tous les éléments <img> finissent de charger. --
wait_for_selector string Non null Sélecteur CSS à attendre avant la capture, appliqué à chaque page. Renvoie 422 s'il n'apparaît jamais dans le délai wait_for_selector_timeout. Utile pour les SPA qui hydratent le contenu après le chargement. --
wait_for_selector_timeout integer Non 10000 Millisecondes d'attente pour wait_for_selector (maximum 60000). --
block_ads boolean Non false Interrompt les requêtes vers les domaines connus de publicité/traçage afin qu'ils ne se chargent jamais, ne s'affichent jamais et ne ralentissent pas la capture. --
block_media boolean Non false Interrompt entièrement les requêtes d'images et audio/vidéo pour un rendu plus rapide et plus léger. Contrairement à load_media (qui contrôle uniquement l'attente), cela empêche totalement le téléchargement des médias. --

Authentification et requêtes personnalisées#

Paramètre Type Requis Défaut Description Restriction de forfait
auth object Non null Identifiants HTTP Basic Auth appliqués à chaque page. Format : {"username": "...", "password": "..."}. Nécessite l'accès basic auth
cookies array Non null Tableau d'objets cookie injectés avant le chargement de chaque page. Maximum 50 cookies. Nécessite l'accès basic auth
headers object Non null En-têtes HTTP personnalisés envoyés avec chaque requête. Maximum 20 en-têtes. Nécessite l'accès basic auth

Options PDF#

Passez-les dans un objet pdf_options. Elles s'appliquent à chaque page du site web.

Paramètre Type Défaut Description
page_size string "A4" Taille de page nommée. Ignorée lorsque page_width et page_height sont tous deux définis.
page_width float null Largeur de page personnalisée en millimètres. page_width et page_height doivent être définis ensemble.
page_height float null Hauteur de page personnalisée en millimètres.
orientation string "portrait" "portrait" ou "landscape".
margins object {"top": 10, "bottom": 10, "left": 10, "right": 10} Marges de page en millimètres.
scale float 1.0 Facteur d'échelle du contenu. Plage : 0.1 à 2.0. Mode paginé uniquement.
grayscale boolean false Convertit chaque page PDF en niveaux de gris.
header object null En-tête de page pour le mode paginé. Format : {"content": "<html>", "height": 15}. Prend en charge les variables de modèle : {{page}}, {{total_pages}}, {{date}}, {{title}}, {{url}}.
footer object null Pied de page pour le mode paginé. Même format que l'en-tête.

Tailles de page prises en charge : A0, A1, A2, A3, A4, A5, A6, B0, B1, B2, B3, B4, B5, Letter, Legal, Tabloid, Ledger


Modes de crawl#

"auto" (par défaut)#

Utilise le mode de crawl le plus élevé que votre forfait autorise. Si votre forfait prend en charge le crawl complet, il exécute un crawl complet. Si votre forfait prend en charge uniquement le sitemap, il exécute la découverte par sitemap.

"sitemap"#

Découvre les pages en analysant le sitemap.xml du site web :

  1. Récupère {base_url}/sitemap.xml (délai de 30 secondes)
  2. Si l'élément racine est <sitemapindex>, récupère récursivement chaque sitemap enfant
  3. Extrait toutes les entrées <url><loc> des éléments <urlset>
  4. Renvoie la liste complète des URL découvertes

Renvoie une erreur si le sitemap est manquant, renvoie un statut différent de 200, contient du XML invalide, ou n'a aucune URL.

"full"#

Effectue un crawl complet en deux phases :

Phase 1 -- Découverte des seeds :

  1. Analyse robots.txt pour les directives de sitemap et les règles de crawl
  2. Vérifie les chemins de sitemap standard (/sitemap.xml, /wp-sitemap.xml, /sitemap_index.xml, etc.)
  3. Découvre les flux RSS/Atom à partir des balises <link> et des chemins de flux courants
  4. Extrait les URL seed de toutes les sources découvertes

Phase 2 -- Crawl de liens en largeur d'abord :

  1. Démarre depuis l'URL de base plus toutes les URL seed
  2. Visite chaque page et met en file d'attente les liens du même domaine
  3. Applique include_patterns et exclude_patterns pour filtrer les liens
  4. Respecte les règles de robots.txt
  5. Détecte et évite les pièges d'URL infinies (pages de calendrier, filtres à facettes, etc.)
  6. Déduplique les URL en normalisant le schéma, l'hôte, les paramètres de requête, et en supprimant les paramètres de suivi (utm_*, fbclid, gclid, etc.)

Motifs d'exclusion par défaut (lorsque exclude_patterns n'est pas fourni) :

  • Ressources statiques : *.pdf, *.zip, *.jpg, *.png, *.gif, *.svg, *.css, *.js, *.xml, *.json, *.mp4, *.webm, *.woff, *.woff2
  • Chemins protégés : /login, /admin, /cart, /checkout
  • Pagination profonde : URL avec des paramètres page= dépassant 3 chiffres

Réponse#

202 Accepted (immédiat)#

{
    "status": "processing",
    "batch_id": "550e8400-e29b-41d4-a716-446655440000",
    "url_count": 42,
    "total_discovered": 42,
    "discovery_method": "sitemap",
    "output_format": "zip"
}
Champ Description
batch_id UUID pour suivre le job via le polling du statut du batch ou le webhook.
url_count Nombre de pages qui seront converties.
total_discovered Nombre total de pages découvertes par le crawl.
discovery_method "sitemap" ou "full_crawl" selon le mode de crawl effectif.

Polling du statut du batch#

Effectuez le polling avec le batch_id de la réponse 202 :

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

Renvoie le statut agrégé, les statuts par URL, et une URL de téléchargement présignée pour le ZIP une fois terminé. Voir Polling du statut du batch pour le schéma complet de la réponse.

Charge utile du callback webhook#

Lorsque callback_url est fourni, Enconvert envoie une requête POST à la fin :

{
    "job_id": "batch-uuid",
    "status": "success",
    "batch_id": "550e8400-e29b-41d4-a716-446655440000",
    "gcs_uri": "env/files/{project_id}/url-to-pdf/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.pdf"},
        {"url": "https://example.com/about", "status": "success", "filename": "example_20260405_002.pdf"},
        {"url": "https://example.com/broken", "status": "failed", "error": "Timeout"}
    ]
}

Notification par e-mail#

Un e-mail de fin est envoyé à notification_email (ou par défaut à l'e-mail du propriétaire du projet) lorsque le job se termine, qu'il réussisse ou échoue.


Restrictions par forfait d'abonnement#

Fonctionnalité Free Starter Pro Enterprise
Capture de site web Non Oui Oui Oui
Mode de crawl sitemap Non Oui Oui Oui
Mode de crawl complet Non Non Oui Oui
Callbacks webhook Non Non Oui Oui
HTTP Basic Auth Non Oui Oui Oui
Injection de cookies Non Oui Oui Oui
En-têtes personnalisés Non Oui Oui Oui
Limite de taille de batch 0 Selon le forfait Selon le forfait Illimité
Conversions mensuelles 100 Selon le forfait Selon le forfait Illimité
Forfait Free : la capture de site web n'est pas disponible sur le forfait gratuit. Toute tentative d'utiliser cet endpoint renvoie 403 Forbidden.

Exemples de code#

Python (clé privée)#

import requests
import time

# Start the website capture
response = requests.post(
    "https://api.enconvert.com/v1/convert/website-to-pdf",
    headers={"X-API-Key": "sk_live_your_private_key"},
    json={
        "url": "https://example.com",
        "crawl_mode": "sitemap",
        "output_filename": "example-website",
        "pdf_options": {
            "page_size": "A4",
            "orientation": "portrait"
        }
    }
)

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_live_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 (clé privée)#

$ch = curl_init("https://api.enconvert.com/v1/convert/website-to-pdf");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Content-Type: application/json",
        "X-API-Key: sk_live_your_private_key"
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "url" => "https://example.com",
        "crawl_mode" => "sitemap",
        "output_filename" => "example-website",
        "pdf_options" => [
            "page_size" => "A4",
            "orientation" => "portrait"
        ]
    ])
]);

$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 (clé privée)#

const response = await fetch("https://api.enconvert.com/v1/convert/website-to-pdf", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "X-API-Key": "sk_live_your_private_key"
    },
    body: JSON.stringify({
        url: "https://example.com",
        crawl_mode: "sitemap",
        output_filename: "example-website",
        pdf_options: {
            page_size: "A4",
            orientation: "portrait"
        }
    })
});

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_live_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 (clé privée)#

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-website",
        "pdf_options": map[string]interface{}{
            "page_size":   "A4",
            "orientation": "portrait",
        },
    })

    req, _ := http.NewRequest("POST", "https://api.enconvert.com/v1/convert/website-to-pdf", bytes.NewBuffer(body))
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("X-API-Key", "sk_live_your_private_key")

    resp, _ := http.DefaultClient.Do(req)
    defer resp.Body.Close()

    respBody, _ := io.ReadAll(resp.Body)
    fmt.Println(string(respBody))
}

Avec callback webhook#

{
    "url": "https://example.com",
    "crawl_mode": "full",
    "callback_url": "https://your-server.com/webhook/enconvert",
    "output_filename": "example-full-site",
    "include_patterns": [".*\\/blog\\/.*", ".*\\/docs\\/.*"],
    "pdf_options": {
        "page_size": "Letter",
        "margins": {"top": 20, "bottom": 20, "left": 15, "right": 15}
    }
}

Avec authentification (site protégé par mot de passe)#

{
    "url": "https://staging.example.com",
    "crawl_mode": "sitemap",
    "auth": {
        "username": "admin",
        "password": "staging-password"
    },
    "cookies": [
        {"name": "session_token", "value": "abc123", "domain": "staging.example.com"}
    ]
}

Réponses d'erreur#

Statut Condition
400 Bad Request Paramètre url manquant ou vide
400 Bad Request Aucune URL trouvée dans le sitemap
400 Bad Request Délai dépassé lors de la récupération du sitemap (limite de 30 secondes)
400 Bad Request Réponse différente de 200 depuis l'URL du sitemap
400 Bad Request XML invalide dans le sitemap
400 Bad Request Format de sitemap non reconnu
400 Bad Request Aucune page découverte (le crawl complet a trouvé zéro URL)
400 Bad Request Structure auth, cookies ou headers invalide
402 Payment Required Limite de conversions mensuelles dépassée par le nombre de pages découvertes
402 Payment Required Limite de stockage atteinte
403 Forbidden Crawl de site web non disponible sur le forfait actuel (forfait Free)
403 Forbidden Le mode de crawl complet nécessite le forfait Pro ou supérieur
403 Forbidden Le nombre de pages découvertes dépasse la limite de taille de batch
403 Forbidden Fonctionnalité non disponible sur le forfait (webhook, basic auth)
500 Internal Server Error Échec du crawl ou de la conversion

Limites#

Limite Valeur
Délai de récupération du sitemap 30 secondes
Délai global du crawl (mode complet) 10 minutes
Profondeur de crawl maximale (mode complet) 10 niveaux
Délai de crawl par page (mode complet) 30 secondes
Limite de mémoire du crawler 512 MB
Seuil de piège infini 20 URL par motif d'URL
Délai de récupération de robots.txt 10 secondes
Nombre maximal de pages par crawl Limite de taille de batch du forfait
Nombre maximal de cookies par requête 50
Nombre maximal d'en-têtes personnalisés par requête 20
Délai de livraison du webhook 30 secondes
Conversions mensuelles Dépend du forfait
Rétention des fichiers Dépend du forfait

Questions fréquentes#

Comment convertir un site web entier en PDF avec une API ?#

Envoyez une requête POST à /v1/convert/website-to-pdf avec l'url de base du site et votre clé privée dans l'en-tête X-API-Key. L'API découvre chaque page (sitemap ou crawl complet), convertit chacune en PDF, les regroupe dans un ZIP, et renvoie HTTP 202 avec un batch_id que vous pouvez interroger pour obtenir le lien de téléchargement.

Quelle est la différence entre le mode de crawl sitemap et le mode de crawl complet ?#

crawl_mode: "sitemap" analyse le sitemap.xml du site (y compris les index de sitemap imbriqués) et est disponible à partir des forfaits Starter. crawl_mode: "full" exécute un crawl en deux phases — découverte des seeds à partir de robots.txt, des sitemaps et des flux RSS/Atom, puis un crawl de liens en largeur d'abord sur le même domaine avec un filtrage include_patterns/exclude_patterns — et nécessite le forfait Pro ou supérieur. Le mode "auto" par défaut utilise le mode le plus élevé que votre forfait autorise.

Comment savoir quand mon job de conversion de site web en PDF est terminé ?#

Interrogez GET /v1/convert/batch/{batch_id} avec votre clé privée pour obtenir le statut agrégé, les statuts par URL, et une URL de téléchargement ZIP présignée, ou transmettez un callback_url pour recevoir un POST webhook à la fin. Un e-mail de fin est également envoyé à notification_email (ou au propriétaire du projet par défaut), que le job réussisse ou échoue.

Puis-je archiver en PDF un site protégé par mot de passe ou un site de staging ?#

Oui, sur les forfaits avec accès basic auth : transmettez auth avec username et password pour l'authentification HTTP Basic appliquée à chaque page, injectez jusqu'à 50 cookies de session, ou envoyez jusqu'à 20 headers personnalisés.

Pourquoi l'endpoint de conversion de site web en PDF renvoie-t-il 403 Forbidden ?#

Les causes les plus courantes : la capture de site web n'est pas disponible sur le forfait Free, crawl_mode: "full" nécessite le forfait Pro ou supérieur, le nombre de pages découvertes dépasse la limite de taille de batch de votre forfait, ou une fonctionnalité demandée (webhook, basic auth) n'est pas incluse dans votre forfait.