API URL vers Markdown#

L'endpoint POST /v1/convert/url-to-markdown convertit toute page web accessible publiquement en Markdown GitHub-Flavored propre, avec un bloc de métadonnées frontmatter YAML. Chaque page est rendue dans un vrai navigateur, puis passée dans un extracteur de lisibilité qui supprime le superflu (navigation, pieds de page, asides, scripts, formulaires, boutons), avant d'être sérialisée en Markdown avec des liens normalisés, des blocs de code délimités, et les URLs relatives résolues en URLs absolues. C'est exactement ce dont les pipelines d'ingestion LLM et RAG ont besoin, à la place du HTML brut. Les conversions s'exécutent en mode synchrone ou asynchrone par lot, et les résultats sont renvoyés sous forme d'octets Markdown bruts ou d'une URL de téléchargement présignée.


Endpoint#

POST /v1/convert/url-to-markdown

Content-Type : application/json

Format de sortie : Markdown (.md, UTF-8) avec un bloc frontmatter YAML en haut du fichier contenant les métadonnées de la page. Le format de sortie n'est pas configurable. Du Markdown avec frontmatter YAML est toujours produit.


Authentification#

Cet endpoint prend en charge l'authentification par clé privée et par clé publique.

Clé privée#

Incluez votre clé secrète dans l'en-tête X-API-Key. Utilisez cette méthode pour les appels serveur à serveur, où la clé n'est jamais exposée au client.

X-API-Key: sk_your_private_key

Clé publique avec JWT#

Pour une utilisation côté client, générez d'abord un token JWT avec votre clé publique, puis passez-le en tant que token Bearer.

Étape 1. Obtenir un token :

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

Étape 2. Utiliser le token :

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Remarque : Les requêtes avec clé publique sont limitées à une seule URL, au mode synchrone et au téléchargement direct. Le mode asynchrone, le traitement par lots, les webhooks et les emails de notification ne sont pas disponibles avec les clés publiques.

Paramètres de requête#

Paramètres de premier niveau#

Parameter Type Required Default Description Plan Gating
url string or string[] Oui -- Une chaîne URL unique ou un tableau d'URLs à convertir. Plusieurs URLs nécessitent le mode asynchrone. --
async_mode boolean Non false Exécute la conversion de manière asynchrone. Renvoie immédiatement un batch_id pour l'interrogation. Requis pour le traitement par lots (plusieurs URLs). Nécessite l'accès au mode asynchrone
direct_download boolean Non false Renvoie les octets Markdown bruts dans le corps de la réponse au lieu d'une réponse JSON avec une URL présignée. Forcé à true pour les clés publiques. Incompatible avec async_mode et plusieurs URLs. --
output_format boolean Non false Quand true avec plusieurs URLs, regroupe tous les fichiers Markdown de sortie dans une archive ZIP unique. Nécessite plusieurs URLs. Nécessite l'accès à la sortie ZIP
output_filename string Non Généré automatiquement Nom de fichier personnalisé pour le fichier de sortie. L'extension .md est ajoutée automatiquement. Format par défaut : {domain}_{timestamp}.md. --
job_id string Non -- ID de tâche fourni par le client pour la reprise après timeout. Clés publiques uniquement. Quand une conversion synchrone dépasse les limites de timeout du reverse proxy, le client peut interroger GET /v1/convert/status/{job_id} pour récupérer le résultat. Ignoré pour les clés privées. --
notification_email string Non Email du propriétaire du projet Adresse email à notifier lorsqu'une tâche asynchrone se termine. Clés privées uniquement. --
callback_url string Non -- URL webhook qui recevra une requête POST lorsque la conversion se termine. Clés privées uniquement. Nécessite l'accès aux webhooks

Paramètres du navigateur et du rendu#

Parameter Type Required Default Description Plan Gating
viewport_width integer Non 1920 Largeur de la fenêtre d'affichage du navigateur en pixels. Affecte le contenu responsive et la variante de mise en page capturée avant l'extraction. --
viewport_height integer Non 1080 Hauteur de la fenêtre d'affichage du navigateur en pixels. Utilisée comme référence pour le rendu et le calcul des unités de viewport. --
load_media boolean Non true Attend que toutes les images et vidéos soient entièrement chargées avant l'extraction. Quand la valeur est false, l'extraction est plus rapide mais les images en chargement différé (lazy-loaded) peuvent conserver des valeurs src de substitution dans la sortie Markdown. --
enable_scroll boolean Non true Fait défiler la page de haut en bas pour déclencher le chargement du contenu différé (chargeurs basés sur IntersectionObserver). --
handle_sticky_header boolean Non true Détecte les en-têtes collants/fixes et fait défiler la page vers le haut avant l'extraction afin de préserver correctement l'ordre du contenu. --
handle_cookies boolean Non true Ferme automatiquement les bannières de consentement aux cookies (OneTrust, Cookiebot, Didomi, Usercentrics, et bannières génériques) avant l'extraction. --
wait_for_images boolean Non true Attend que tous les éléments <img> terminent de charger (timeout de 5 secondes par image) afin que le texte alt et les valeurs src finales soient capturés correctement. --
wait_for_selector string Non null Sélecteur CSS à attendre avant l'extraction. 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 et ne ralentissent pas l'extraction. --
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#

Parameter Type Required Default Description Plan Gating
auth object Non null Identifiants HTTP Basic Auth pour l'URL cible. Format : {"username": "...", "password": "..."}. Ne peut pas être utilisé en même temps qu'un en-tête personnalisé Authorization. Nécessite l'accès à l'authentification de base
cookies array Non null Tableau d'objets cookie à injecter avant la navigation. Maximum 50 cookies. Chaque cookie doit avoir name, value, et soit domain soit url. Nécessite l'accès à l'authentification de base
headers object Non null Dictionnaire d'en-têtes HTTP personnalisés envoyés avec chaque requête vers l'URL cible. Maximum 20 en-têtes. En-têtes bloqués : host, content-length, transfer-encoding, connection, upgrade, te, trailer. Nécessite l'accès à l'authentification de base
Non pris en charge : Les paramètres single_page et pdf_options de l'endpoint url-to-pdf sont acceptés par souci de cohérence de forme des requêtes, mais n'ont aucun effet sur la sortie Markdown. Markdown n'a pas de notion de pages, de marges ou d'orientation.

Chaque élément du tableau cookies doit respecter cette structure :

Field Type Required Default Description
name string Oui -- Nom du cookie.
value string Oui -- Valeur du cookie.
domain string Conditionnel -- Domaine du cookie. domain ou url doit être fourni.
url string Conditionnel -- URL à associer au cookie. domain ou url doit être fourni.
path string Non "/" Chemin du cookie. Par défaut "/" quand domain est défini.

Réponse#

Synchrone avec téléchargement direct (direct_download=true)#

Clé privée renvoie les octets Markdown bruts :

HTTP 200 OK
Content-Type: text/markdown; charset=utf-8
Content-Disposition: inline; filename="example_20260421_123456789.md"
X-Object-Key: env/files/{project_id}/url-to-markdown/example_20260421_123456789.md
X-File-Size: 8421
X-Conversion-Time: 6.3
X-Filename: example_20260421_123456789.md

(UTF-8 Markdown with YAML frontmatter)

Clé publique renvoie du JSON avec une URL présignée :

{
    "presigned_url": "https://spaces.example.com/...",
    "object_key": "env/files/{project_id}/url-to-markdown/example_20260421_123456789.md",
    "filename": "example_20260421_123456789.md",
    "file_size": 8421,
    "conversion_time_seconds": 6.3,
    "job_id": "client-provided-id"
}

Synchrone sans téléchargement direct (direct_download=false)#

Disponible uniquement avec les clés privées.

{
    "presigned_url": "https://spaces.example.com/...",
    "object_key": "env/files/{project_id}/url-to-markdown/example_20260421_123456789.md",
    "filename": "example_20260421_123456789.md",
    "file_size": 8421,
    "conversion_time_seconds": 6.3
}

Mode asynchrone#

Renvoie immédiatement un batch_id pour l'interrogation.

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

Quand output_format=true (regroupement ZIP) :

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

Interrogation du statut de la tâche (clés publiques uniquement)#

Pour la reprise après timeout avec une clé publique :

GET /v1/convert/status/{job_id}
Authorization: Bearer <jwt_token>
Status Response
En cours {"status": "processing"}
Succès {"status": "success", "presigned_url": "...", "object_key": "..."}
Échec {"status": "failed", "error": "..."}

Interrogation du statut du lot (clés privées uniquement)#

Pour les tâches asynchrones par lot, interrogez avec le batch_id reçu dans la réponse 202 :

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

Renvoie le statut agrégé, les statuts par URL, ainsi que des URLs de téléchargement présignées. Voir Interrogation du statut du lot pour le schéma complet de la réponse.

Charge utile du callback webhook#

Quand un callback_url est fourni, EnConvert envoie une requête POST à cette URL à la fin de la conversion.

Tâche avec une seule URL :

{
    "job_id": "activity_id",
    "status": "success",
    "batch_id": "...",
    "gcs_uri": "object_key",
    "filename": "example_20260421_123456789.md",
    "file_size": 8421
}

Tâche par lot :

{
    "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.md"},
        {"url": "https://example.com/page2", "status": "failed", "filename": null}
    ]
}

Format de sortie#

Chaque fichier Markdown commence par un bloc frontmatter YAML contenant les métadonnées de la page, suivi du corps de l'article extrait.

---
url: https://example.com/articles/my-post
title: My Post Title
description: A short summary from the meta description or og:description tag.
links:
  - url: https://example.com/related
    text: Related article
  - url: https://example.com/about
    text: About the author
images:
  - url: https://example.com/hero.jpg
    alt: Hero image alt text
  - url: https://example.com/diagram.png
    alt: Architecture diagram
---

# My Post Title

Opening paragraph of the article body, converted to GitHub-Flavored Markdown...

## A Section Heading

- List item one
- List item two

\`\`\`python
def example():
    return "code blocks are fenced with language hints"
\`\`\`

[A link in the body](https://example.com/linked-page)

![An image in the body](https://example.com/inline-image.png)

Champs du frontmatter#

Field Type Description
url string L'URL finale après redirections (ce n'est pas toujours l'URL que vous avez envoyée).
title string Le titre de la page issu de <title>, avec repli sur le titre court détecté par Readability.
description string La valeur de <meta name="description">, avec repli sur <meta property="og:description">.
links array Chaque <a href> trouvé sur la page, avec les URLs absolues et le texte d'ancrage visible.
images array Chaque <img src> trouvé sur la page, avec les URLs absolues et le texte alt.

Conventions Markdown#

  • Style de titre : ATX (#, ##, ###)
  • Puces de liste : -
  • Emphase : *bold*, *italic* avec échappement de * et _ dans le texte littéral
  • Retours à la ligne souples : deux espaces en fin de ligne (préservés dans la sortie)
  • Blocs de code : délimités (```) avec indices de langage détectés depuis class="language-xxx", class="lang-xxx", class="highlight-source-xxx", data-lang, et data-language
  • Liens : [text](url) quand un texte d'ancrage est présent, forme autolink <url> quand l'ancrage est vide, les liens uniquement ancrés (#foo) et les liens javascript: sont convertis en texte brut
  • Images : ![alt](src), avec title préservé quand présent, avec repli sur data-src quand src est absent (images en chargement différé)
  • Règles horizontales : ---

Fonctionnalités#

Extraction propre du contenu#

EnConvert utilise l'algorithme Readability (la même bibliothèque qui alimente le mode lecture de Firefox) pour isoler le contenu principal de l'article du reste de la page, puis applique une seconde passe de post-traitement pour produire du Markdown propre.

Supprimé avant la conversion :

  • Navigation (<nav>), pieds de page (<footer>), asides (<aside>)
  • Scripts (<script>, <noscript>), styles (<style>), iframes, formulaires, boutons
  • SVG en ligne, canvas et éléments template
  • Les attributs style, class, id, et tous les gestionnaires d'événements on*

Préservé :

  • Titres, paragraphes, listes, tableaux, citations, blocs de code
  • Liens avec leur href et leur texte d'ancrage (URLs absolues)
  • Images avec alt, title, et src absolu
  • Figures et figcaptions (les images en ligne y sont conservées)

Mode de capture claire#

Avant l'extraction, la page est rendue dans un vrai navigateur et nettoyée de la même manière que pour url-to-pdf :

  • Bannières de consentement aux cookies : fermées automatiquement sur la page principale et les iframes (OneTrust, Cookiebot, Didomi, Usercentrics, et bannières génériques).
  • Fermeture des modales et popups : les overlays sont fermés via la touche Échap, les boutons de fermeture ARIA, les boutons de fermeture basés sur des classes, et les boutons de dialogue basés sur des rôles.
  • Révélation des animations au défilement : force la visibilité des éléments masqués par WOW.js, AOS, ScrollReveal, GSAP ScrollTrigger, et les classes d'animation génériques.
  • Gestion des en-têtes collants : les en-têtes collants/fixes sont détectés et la page est ramenée en haut afin de préserver l'ordre du contenu.

Résolution des URLs absolues#

Chaque href et src relatif dans l'article extrait est résolu par rapport à l'URL finale de la page (après redirections), de sorte que la sortie Markdown contient toujours des liens absolus et cliquables, ce qui est utile pour les pipelines d'ingestion LLM qui verraient sinon des chemins relatifs cassés.

Les liens uniquement ancrés (#section), les liens javascript:, mailto:, et tel: ne sont pas réécrits. Les liens uniquement ancrés et les liens javascript: sont convertis en texte brut car ils n'ont aucun sens en dehors de la page d'origine.

Détection du langage des blocs de code#

Les blocs de code sont délimités avec un indice de langage détecté quand c'est possible :

<pre><code class="language-python">...</code></pre>    →   ```python
<pre data-lang="js">...</pre>                          →   ```js
<pre><code class="highlight-source-shell">...</code></pre> →   ```shell

Les classes correspondant à language-*, lang-*, highlight-source-*, et brush:* sont reconnues, ainsi que les attributs data-lang et data-language sur le <pre> et son <code> imbriqué. Si aucun indice n'est trouvé, le bloc est délimité sans étiquette de langage.

HTTP Basic Auth#

Passez auth avec username et password pour convertir des pages protégées par HTTP Basic Authentication.

{
    "url": "https://staging.example.com/docs/article",
    "auth": {
        "username": "admin",
        "password": "secret"
    }
}

Injection de cookies#

Injectez jusqu'à 50 cookies avant le chargement de la page. Utile pour convertir des pages d'articles réservées aux membres ou spécifiques à une locale.

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

En-têtes personnalisés#

Envoyez jusqu'à 20 en-têtes HTTP personnalisés avec chaque requête vers la page cible.

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

Chargement différé des images#

Quand load_media et enable_scroll sont activés (tous deux à true par défaut), le convertisseur fait défiler la page lentement pour déclencher les chargeurs différés, puis attend que toutes les images terminent de charger avant de capturer le HTML final. Cela garantit que les valeurs data-src ont été promues en véritables valeurs src et que la liste images du frontmatter est complète.

Définissez load_media=false pour une extraction plus rapide quand vous n'avez besoin que du corps textuel. Des valeurs src de substitution peuvent alors subsister dans la sortie.

Fonctionnalités de rendu supplémentaires#

  • Normalisation des unités de viewport : les unités CSS de viewport (vh, svh, lvh, dvh) sont converties en valeurs de pixels fixes avant l'extraction.
  • Mode furtif : masquage de l'empreinte du navigateur pour éviter la détection de bot sur les pages protégées.
  • Interception des popups : ferme automatiquement tout nouvel onglet ou popup déclenché par la page.
  • Contournement CSP : gère les restrictions Content Security Policy et Trusted Types qui bloqueraient sinon la manipulation de la page.

Restrictions liées au forfait d'abonnement#

Feature Founding Indie Studio Enterprise
Conversion basique (URL unique, synchrone) Oui Oui Oui Oui
Options de viewport et de rendu Oui Oui Oui Oui
Mode asynchrone Non Oui Oui Oui
Traitement par lots (plusieurs URLs) Non Oui Oui Oui
Regroupement de sortie ZIP 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
Conversions mensuelles 100 Selon le forfait Selon le forfait Illimité
Limite de taille de lot 0 Selon le forfait Selon le forfait Illimité
Rétention des fichiers 1 heure Selon le forfait Selon le forfait Selon le forfait

Mode asynchrone#

Le mode asynchrone est utile pour les conversions longues ou lors de la conversion de plusieurs URLs.

Fonctionnement#

  1. Envoyez une requête avec async_mode=true (ou passez plusieurs URLs, ce qui active automatiquement le mode asynchrone).
  2. L'API renvoie immédiatement un HTTP 202 avec un batch_id et un url_count.
  3. Chaque URL est convertie en arrière-plan, envoyée vers le stockage, et suivie individuellement.
  4. Suivez l'achèvement via l'interrogation du statut du lot, la notification par email, ou le callback webhook.

Notification par email#

Par défaut, un email d'achèvement est envoyé à l'adresse email du propriétaire du projet. Remplacez-la avec notification_email :

{
    "url": ["https://example.com/page1", "https://example.com/page2"],
    "async_mode": true,
    "notification_email": "[email protected]"
}

Callback webhook#

Fournissez un callback_url pour recevoir une notification POST automatique à l'achèvement :

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

Le webhook est envoyé avec un timeout de 30 secondes et considère les codes HTTP 200, 201, 202, et 204 comme une livraison réussie.


Traitement par lots et en masse#

Convertissez plusieurs URLs en une seule requête. Nécessite le mode asynchrone et une clé privée.

Sortie individuelle (par défaut)#

Chaque URL produit un fichier Markdown séparé :

{
    "url": [
        "https://example.com/post-1",
        "https://example.com/post-2",
        "https://example.com/post-3"
    ],
    "async_mode": true
}

Sortie en archive ZIP#

Regroupez tous les fichiers Markdown dans une archive ZIP unique :

{
    "url": [
        "https://example.com/post-1",
        "https://example.com/post-2",
        "https://example.com/post-3"
    ],
    "async_mode": true,
    "output_format": true,
    "output_filename": "blog-archive"
}

Le fichier ZIP est nommé {output_filename}_{timestamp}.zip ou batch_{timestamp}.zip si aucun nom personnalisé n'est fourni.


Exemples de code#

Python (clé privée)#

import requests

response = requests.post(
    "https://api.enconvert.com/v1/convert/url-to-markdown",
    headers={"X-API-Key": "sk_your_private_key"},
    json={
        "url": "https://example.com/articles/my-post",
        "direct_download": True
    }
)

response.raise_for_status()
markdown_text = response.content.decode("utf-8")
print(markdown_text)

PHP (clé privée)#

$ch = curl_init("https://api.enconvert.com/v1/convert/url-to-markdown");
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/articles/my-post"
    ])
]);

$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
echo $data["presigned_url"];

Node.js (clé privée)#

const response = await fetch("https://api.enconvert.com/v1/convert/url-to-markdown", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "X-API-Key": "sk_your_private_key"
    },
    body: JSON.stringify({
        url: "https://example.com/articles/my-post"
    })
});

const data = await response.json();
console.log(data.presigned_url);

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/articles/my-post",
    })

    req, _ := http.NewRequest("POST", "https://api.enconvert.com/v1/convert/url-to-markdown", 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 côté navigateur (clé publique)#

// 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: Convert URL to Markdown (public keys receive raw bytes)
const convertRes = await fetch("https://api.enconvert.com/v1/convert/url-to-markdown", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${token}`
    },
    body: JSON.stringify({
        url: "https://example.com/articles/my-post"
    })
});

const markdown = await convertRes.text();
console.log(markdown);

React (clé publique)#

import { useState } from "react";

function UrlToMarkdown() {
    const [loading, setLoading] = useState(false);
    const [markdown, setMarkdown] = useState("");

    async function convertUrl() {
        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();

            // Convert
            const convertRes = await fetch("https://api.enconvert.com/v1/convert/url-to-markdown", {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    "Authorization": `Bearer ${token}`
                },
                body: JSON.stringify({ url: "https://example.com/articles/my-post" })
            });

            setMarkdown(await convertRes.text());
        } finally {
            setLoading(false);
        }
    }

    return (
        <div>
            <button onClick={convertUrl} disabled={loading}>
                {loading ? "Converting..." : "Convert to Markdown"}
            </button>
            {markdown && <pre>{markdown}</pre>}
        </div>
    );
}

export default UrlToMarkdown;

Réponses d'erreur#

Status Condition
400 Bad Request Paramètre url manquant ou vide
400 Bad Request output_format=true avec une seule URL (plusieurs URLs requises)
400 Bad Request direct_download=true avec plusieurs URLs
400 Bad Request direct_download=true avec async_mode=true
400 Bad Request Objet auth invalide (username ou password manquant)
400 Bad Request cookies invalide (n'est pas un tableau, dépasse 50 entrées, champs requis manquants)
400 Bad Request headers invalide (n'est pas un objet, dépasse 20 entrées, noms d'en-tête bloqués, valeurs non textuelles)
400 Bad Request Conflit entre auth et l'en-tête personnalisé Authorization
400 Bad Request Clé publique tentant plusieurs URLs
401 Unauthorized Clé API / token JWT manquant ou invalide
402 Payment Required Quota mensuel d'ops épuisé
402 Payment Required Le lot dépasserait le quota mensuel d'ops restant
402 Payment Required Limite de stockage atteinte
403 Forbidden Endpoint non inclus dans les endpoints autorisés de la clé API
403 Forbidden Fonctionnalité non disponible sur le forfait actuel (asynchrone, webhook, ZIP, basic auth)
403 Forbidden La taille du lot dépasse la limite du forfait
404 Not Found ID de tâche introuvable (lors de l'interrogation du statut)
500 Internal Server Error Échec de la conversion (crash du navigateur, erreur de navigation, échec de l'extraction)

Limites#

Limit Value
Timeout de navigation de page 60 secondes
Timeout de chargement par image 5 secondes
Timeout de fermeture de la bannière cookies 3 secondes
Nombre maximum de cookies par requête 50
Nombre maximum d'en-têtes personnalisés par requête 20
Opérations mensuelles Selon le forfait (Founding : 500)
Taille de lot Selon le forfait (Founding : désactivé)
Rétention des fichiers Selon le forfait (Founding : 1 heure)
Timeout de livraison webhook 30 secondes

Questions fréquentes#

Comment convertir une page web en Markdown avec une API REST ?#

Envoyez une requête POST à /v1/convert/url-to-markdown avec un url dans le corps JSON et votre clé dans l'en-tête X-API-Key. Vous recevez en retour une réponse JSON avec un presigned_url vers le fichier Markdown, ou les octets Markdown UTF-8 bruts si vous définissez direct_download=true.

Puis-je convertir des pages web en Markdown pour des pipelines LLM et RAG ?#

Oui. La sortie est conçue pour l'ingestion LLM. L'algorithme Readability (la même bibliothèque derrière le mode lecture de Firefox) isole l'article principal, le superflu comme <nav>, <footer>, les scripts et les formulaires est supprimé, chaque lien et URL d'image relatifs sont résolus en URL absolue, et un bloc frontmatter YAML porte les champs url, title, description, links, et images de la page.

Puis-je convertir plusieurs URLs en Markdown en une seule requête API ?#

Oui. Passez un tableau d'URLs dans url avec async_mode=true (nécessite une clé privée et un forfait avec accès au traitement par lots) ; l'API renvoie un HTTP 202 avec un batch_id que vous interrogez via GET /v1/convert/batch/{batch_id}. Définissez output_format=true pour regrouper tous les fichiers Markdown dans une archive ZIP unique.

Pourquoi certaines images de ma sortie Markdown ont-elles des valeurs src de substitution ?#

Cela se produit quand load_media=false. L'extraction est plus rapide mais les images en chargement différé peuvent conserver des valeurs src de substitution. Laissez load_media et enable_scroll à leur valeur par défaut true afin que la page défile pour déclencher les chargeurs différés et que chaque image termine de charger (timeout de 5 secondes par image) avant la capture.

L'API URL vers Markdown fonctionne-t-elle sur des pages protégées par une connexion ?#

Oui, sur les forfaits avec accès à l'authentification de base : passez auth avec username et password pour HTTP Basic Auth, injectez jusqu'à 50 cookies de session, ou envoyez jusqu'à 20 headers personnalisés, ce qui est utile pour les pages d'articles réservées aux membres ou en environnement de préproduction (staging).