# Page web en Markdown dans Node.js

> Convertissez des pages web en Markdown dans Node.js : une page, un pool de concurrence et une boucle de polling. Depuis 0,07 $US/1K pages, sans KYC, en crypto.

- URL: https://webreaderapi.com/fr/docs/node/
- Dernière mise à jour: 2026-10-22
- Éditeur: WebReaderAPI (https://webreaderapi.com)

Node.js 18 et les versions suivantes embarquent `fetch`, donc vous n'avez besoin d'aucune dépendance. Trois recettes : lire une page, lire une liste avec un petit pool de concurrence, et suivre un job de crawl jusqu'à sa fin.

**Réponse rapide — Comment convertir une page web en Markdown dans Node.js ?**

Utilisez le `fetch` intégré de Node.js 18+ : appelez `https://webreaderapi.com/api/v1/read?url=…` avec votre clé dans l'en-tête `Authorization` et lisez `markdown` dans la réponse JSON. **WebReaderAPI** renvoie le contenu principal de la page avec son titre, son auteur et sa date. Une page coûte 1 crédit, 2 avec un navigateur, depuis 0,07 $US/1K pages en octobre 2026. Sans KYC ; payez en crypto.

## De quoi ai-je besoin ?

Node.js 18 ou plus récent, pour le `fetch` global, et une clé API dans la variable d'environnement `WEBREADER_API_KEY`. Les exemples sont des modules ES : enregistrez-les avec l'extension `.mjs`, ou définissez `"type": "module"` dans votre `package.json`, pour que le `await` de haut niveau fonctionne.

Les commentaires JSDoc décrivent la forme de la réponse, donc des éditeurs comme VS Code vous offrent la complétion sans étape de build TypeScript.

*read.mjs : une page*

```javascript
/**
 * @typedef {Object} Page
 * @property {string} url
 * @property {string} final_url
 * @property {number} status_code
 * @property {boolean} rendered
 * @property {number} credits_used
 * @property {string} [title]
 * @property {string} [author]
 * @property {string} [published_at]
 * @property {string} [language]
 * @property {string} [markdown]
 * @property {number} word_count
 */

/** @returns {Promise<Page>} */
export async function readPage(url, options = {}) {
  const params = new URLSearchParams({ url, ...options });
  const res = await fetch(`https://webreaderapi.com/api/v1/read?${params}`, {
    headers: { Authorization: `Bearer ${process.env.WEBREADER_API_KEY}` },
    signal: AbortSignal.timeout(75_000),
  });
  const body = await res.json();
  if (!res.ok) throw Object.assign(new Error(body.error.message), { code: body.error.code });
  return body;
}

const page = await readPage('https://example.com/docs/getting-started', { max_chars: '20000' });
console.log(page.title, page.word_count, 'words,', page.credits_used, 'credit(s)');

```

## Comment lire une liste d'URL sans atteindre la limite ?

Lancez un nombre fixe de workers qui prennent des URL dans une file partagée. C'est plus simple que `Promise.all` sur toute la liste, ce qui lancerait toutes les requêtes à la fois et atteindrait `429 concurrency_limit`. Chaque compte a une limite du nombre de pages lues en simultané ; votre dashboard l'affiche, et le support peut l'augmenter.

Le pool ci-dessous garde les erreurs à côté des résultats, donc une page refusée n'arrête pas l'exécution. Les refus comme `blocked_by_robots` sont définitifs et gratuits ; comptez-les et passez à la suite.

*pool.mjs : une liste d'URL, 8 à la fois*

```javascript
import { readPage } from './read.mjs';

export async function readAll(urls, workers = 8) {
  const queue = [...urls];
  const results = [];
  async function worker() {
    while (queue.length) {
      const url = queue.shift();
      try {
        const page = await readPage(url, { max_chars: '50000' });
        results.push({ url, page });
      } catch (err) {
        results.push({ url, error: err.code ?? err.name });
      }
    }
  }
  await Promise.all(Array.from({ length: workers }, worker));
  return results;
}

const urls = Array.from({ length: 30 }, (_, i) => `https://example.com/blog/post-${i + 1}`);
for (const r of await readAll(urls)) console.log(r.url, '->', r.error ?? r.page.title);

```

## Comment suivre un job de crawl dans Node.js ?

Démarrez le job avec `POST https://webreaderapi.com/api/v1/crawl`, puis lisez `https://webreaderapi.com/api/v1/jobs/{job_id}` dans une boucle. Passez `cursor` à chaque fois que `next_cursor` revient ; quand il n'y a pas de curseur et que le statut est `done`, le job est terminé. Attendez entre les polls vides et doublez l'attente jusqu'à 30 secondes, car un crawl qui respecte le Crawl-delay d'un site peut être lent.

La [page batch and crawl](https://webreaderapi.com/fr/docs/crawl/) décrit comment le crawl choisit ses pages et comment `limit` plafonne ce qu'il lit.

*crawl.mjs : démarrer un crawl et collecter chaque page*

```javascript
const headers = {
  Authorization: `Bearer ${process.env.WEBREADER_API_KEY}`,
  'Content-Type': 'application/json',
};
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

const start = await fetch('https://webreaderapi.com/api/v1/crawl', {
  method: 'POST',
  headers,
  body: JSON.stringify({ url: 'https://docs.example.com/', limit: 300, include_paths: ['/docs/*'] }),
});
const { job_id } = await start.json();

const pages = [];
let cursor = '';
let wait = 2000;
for (;;) {
  const url = `https://webreaderapi.com/api/v1/jobs/${job_id}${cursor ? `?cursor=${encodeURIComponent(cursor)}` : ''}`;
  const job = await (await fetch(url, { headers })).json();
  pages.push(...job.results.filter((r) => !r.error));
  if (job.next_cursor) {
    cursor = job.next_cursor;
    wait = 2000;
    continue;
  }
  if (job.status === 'done') break;
  await sleep(wait);
  wait = Math.min(wait * 2, 30000);
}
console.log(pages.length, 'pages read, job', job_id);

```

## Comment passer le résultat à un modèle ?

Envoyez le Markdown, pas le JSON entier. Le champ `markdown` est ce qu'un modèle doit lire ; les métadonnées sont mieux gardées pour les citations. Préfixez avec le titre et `final_url`, pour que le modèle puisse nommer sa source, et gardez `max_chars` à une taille que le contexte de votre modèle peut contenir, par exemple 20 000 caractères par page.

La [page OpenAI function calling](https://webreaderapi.com/fr/docs/openai/) montre la boucle d'outil complète en Python ; la même fonction `readPage` ci-dessus peut servir de corps d'outil dans un agent Node.js.

## Node.js : questions fréquentes

### Est-ce que cela fonctionne dans Deno, Bun ou le navigateur ?

Deno et Bun prennent en charge le même `fetch` et les modules ES. N'appelez pas l'API depuis une page de navigateur : la clé serait visible par chaque visiteur. Appelez-la depuis votre serveur à la place.

### Existe-t-il un package npm ?

Non. Les fonctions de cette page constituent l'intégration complète. WebReaderAPI est du HTTPS et du JSON simples, donc vous gardez le contrôle des retries, des timeouts et du logging.

### Comment gérer 429 concurrency_limit ?

Réduisez le nombre de workers, ou réessayez après une courte attente qui double à chaque fois. Un 429 ne coûte rien, et la [page errors](https://webreaderapi.com/fr/docs/errors/) propose une fonction de backoff prête à l'emploi.

### Combien coûte la lecture de 10 000 pages ?

Environ 10 000 crédits pour des pages simples, davantage si certaines nécessitent un navigateur. 10 000 pages coûtent 3,75 $US ; Les crédits prépayés n'expirent jamais : les pages non utilisées restent sur votre compte jusqu'à ce que vous les utilisiez.

---

WebReaderAPI: WebReaderAPI est une API de lecture de pages web pour agents IA qui transforme toute page web publique en Markdown propre, payable en crypto sans envoi de pièce d'identité. Les crédits prépayés à partir de 0,07 $US/1K pages n'expirent jamais, et robots.txt est respecté. Sans KYC — pas de pièce d'identité, pas de selfie, pas de documents. Payez en crypto.
