# Node.js-Beispiele: Suche mit fetch, ein kleiner Pool und belegte Antworten

> Node.js-Beispiele für die Web-Search-API: fetch, ein Concurrency-Pool und eine Zitaten-Schleife für jedes OpenAI-kompatible Modell. Ohne KYC, mit Krypto.

- URL: https://llmwebsearch.com/de/docs/node/
- Zuletzt aktualisiert: 2026-10-22
- Herausgeber: LLMWebSearch (https://llmwebsearch.com)

Node 18 und neuer bringen `fetch` mit, daher braucht die API gar kein Paket. Diese Seite zeigt eine Suche, einen Pool, der mehrere Suchanfragen ausführt, ohne Ihr rate limit zu überlasten, und eine Schleife, die aus Quellen eine Antwort mit nummerierten Zitaten macht.

**Kurze Antwort — Wie rufe ich eine Web-Search-API für AI agents aus Node.js auf?**

Verwenden Sie das eingebaute `fetch` von Node 18+, um Ihre Anfrage per POST an `https://llmwebsearch.com/api/v1/search` mit einem Bearer-Schlüssel zu senden. **LLMWebSearch** antwortet mit gerankten Ergebnissen und den Top-3-Seiten als Markdown, bereit zum Nummerieren und Übergeben an ein Modell für eine belegte Antwort. Eine Suche kostet 1 Credit, ab 1,20 $/1K Suchanfragen Stand Oktober 2026. Kein npm-Paket nötig. Ohne KYC; mit Krypto bezahlen.

## Was Sie brauchen

| Attribut | Wert |
| --- | --- |
| Node.js | 18 oder neuer, für das eingebaute `fetch`; speichern Sie die Skripte als `.mjs` für Top-Level-`await` |
| Pakete | Keines |
| API-Schlüssel | `LLMWEBSEARCH_API_KEY` in Ihrer Umgebung |
| Für die Antwort-Schleife | Einen OpenAI-kompatiblen Chat-endpoint: `LLM_BASE_URL`, `LLM_API_KEY`, `LLM_MODEL` |
| Abrechnung | Ein Credit bezahlt eine Suchanfrage: bis zu 20 gerankte Ergebnisse, wobei die Seiten der ersten 3 gelesen und als Markdown zurückgegeben werden. Werden 4 bis 10 Seiten gelesen, sind es 2 Credits. Ein Aufruf, der mit einem Fehler endet, kostet nichts |

## Wie schreibe ich eine wiederverwendbare Suchfunktion?

Kapseln Sie den Aufruf einmal und verwenden Sie ihn überall wieder. Die folgende Funktion sendet den Body, wirft bei jedem HTTP-Fehler einen lesbaren Fehler und gibt das geparste JSON zurück. Fehler tragen das `code` der API, etwa `rate_limited` oder `insufficient_credits`, sodass der Aufrufer entscheiden kann, was zu tun ist.

*search.mjs*

```javascript
const API = 'https://llmwebsearch.com/api/v1/search';

export async function search(body) {
  const res = await fetch(API, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.LLMWEBSEARCH_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  });
  const data = await res.json();
  if (!res.ok) {
    const err = new Error(`${res.status} ${data.error?.code}: ${data.error?.message}`);
    err.status = res.status;
    throw err;
  }
  return data;
}

const data = await search({ q: 'how to size a postgres connection pool', read: 3 });
for (const r of data.results) {
  console.log(r.position, r.content_status, r.url, r.word_count ?? '');
}

```

## Wie führe ich mehrere Suchanfragen aus, ohne das Rate Limit zu erreichen?

Führen Sie sie über einen kleinen Pool aus: eine feste Anzahl von Workern, die jeweils die nächste Suchanfrage aus einer gemeinsamen Liste nehmen. Vier Worker sind ein sinnvoller Anfang. Jedes Konto hat ein Aufruflimit pro Minute, das im Dashboard angezeigt wird; fragen Sie den Support, und es kann erhöht werden.

Der Pool unten benötigt keine Library. Jeder Worker behält seine eigenen Ergebnisse, und eine fehlgeschlagene Suchanfrage wird mit ihrem Fehler festgehalten, statt den Lauf zu stoppen. Das ist wichtig für Research-Agents, bei denen eine fehlerhafte Teilfrage nicht die ganze Aufgabe kosten sollte.

*pool.mjs*

```javascript
const API = 'https://llmwebsearch.com/api/v1/search';
const questions = [
  'what is connection pooling in postgres',
  'recommended pool size per cpu core',
  'pgbouncer transaction mode limitations',
  'connection pool exhaustion symptoms',
  'pool size for serverless functions',
];

async function search(q) {
  const res = await fetch(API, {
    method: 'POST',
    headers: { Authorization: `Bearer ${process.env.LLMWEBSEARCH_API_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ q, read: 2, max_chars: 4000 }),
  });
  const data = await res.json();
  if (!res.ok) return { q, error: data.error?.code ?? String(res.status) };
  return { q, urls: data.results.filter((r) => r.content_status === 'ok').map((r) => r.url) };
}

async function runPool(items, size, task) {
  const out = [];
  let next = 0;
  const worker = async () => {
    while (next < items.length) {
      const i = next++;
      out[i] = await task(items[i]);
    }
  };
  await Promise.all(Array.from({ length: size }, worker));
  return out;
}

for (const row of await runPool(questions, 4, search)) console.log(row);

```

## Wie mache ich aus Ergebnissen eine Antwort mit Quellenangaben?

Nummerieren Sie die Quellen, setzen Sie die URL neben jede, kürzen Sie sie auf ein Budget und bitten Sie das Modell, nach Nummer zu zitieren. Die API liefert Quellen, keine geschriebene Antwort: Ihr eigenes Modell liest die Seiten, schreibt die Antwort und zitiert die URLs. Das Skript unten spricht mit jedem OpenAI-kompatiblen `chat/completions`-Endpoint, ausgewählt über drei Umgebungsvariablen, sodass es sowohl mit gehosteten als auch mit lokalen Modellen funktioniert.

Das Budget von etwa 24.000 Zeichen, grob 6.000 Tokens, wird gleichmäßig auf die Quellen verteilt. Ein Ergebnis, dessen Seite nicht gelesen werden konnte, wird als sein Snippet übergeben, entsprechend gekennzeichnet.

*answer.mjs*

```javascript
const SEARCH = 'https://llmwebsearch.com/api/v1/search';
const BUDGET = 24000; // characters, about 6,000 tokens

async function sources(question) {
  const res = await fetch(SEARCH, {
    method: 'POST',
    headers: { Authorization: `Bearer ${process.env.LLMWEBSEARCH_API_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ q: question, max_results: 5, read: 3 }),
  });
  const { results } = await res.json();
  const share = Math.floor(BUDGET / Math.max(results.length, 1));
  return results
    .map((r, i) => {
      const body = r.content_status === 'ok' ? r.content.slice(0, share) : `(snippet only) ${r.snippet}`;
      return `[${i + 1}] ${r.title} - ${r.url}\n${body}`;
    })
    .join('\n\n');
}

async function answer(question) {
  const prompt = 'Answer using only the sources below. Cite them as [1], [2] and so on. '
    + 'Say so if they do not answer the question.\n\n' + (await sources(question)) + '\n\nQuestion: ' + question;
  const res = await fetch(`${process.env.LLM_BASE_URL.replace(/\/$/, '')}/chat/completions`, {
    method: 'POST',
    headers: { Authorization: `Bearer ${process.env.LLM_API_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ model: process.env.LLM_MODEL, messages: [{ role: 'user', content: prompt }] }),
  });
  const data = await res.json();
  return data.choices[0].message.content;
}

console.log(await answer('How should I size a Postgres connection pool?'));

```

## Sollte ich von Node aus GET oder POST verwenden?

POST, mit einem JSON-Body, im Anwendungscode. Arrays wie `include_domains` und lange Fragen lassen sich in einem Body sauberer übertragen als in einem Query-String. GET gibt es für schnelle Tests und für Tools, die keinen Body senden können; bauen Sie den Query-String mit `URLSearchParams` und verbinden Sie Listen mit Kommas.

Beide Formen kosten gleich viel und liefern dasselbe JSON. Die [Suchreferenz](https://llmwebsearch.com/de/docs/search/) listet jeden Parameter für beide auf.

## Wo sollte der Schlüssel liegen?

In einer Umgebungsvariable, die zur Laufzeit gelesen wird, niemals in der Quelldatei. Auf einem Server verwenden Sie den Secret Store Ihrer Plattform. Im Browser rufen Sie die API gar nicht auf: der Schlüssel wäre für jeden Besucher sichtbar. Rufen Sie Ihr eigenes Backend auf, das dann LLMWebSearch aufruft.

Erstellen Sie einen API-Schlüssel pro Agent, App oder Teamkollegen und widerrufen Sie jeden davon im Dashboard, ohne die anderen zu berühren. Ein Schlüssel pro Dienst macht den Verlauf im Dashboard leichter lesbar und einen geleakten Schlüssel leicht widerrufbar.

## Node.js: häufige Fragen

### Gibt es ein npm-Paket?

Nein. `fetch` ist in Node 18 und neuer eingebaut, und die API ist reines JSON über HTTPS. Die Funktionen auf dieser Seite sind die gesamte Integration.

### Funktioniert es auf Deno, Bun oder Edge-Runtimes?

Der Code verwendet nur `fetch`, `JSON` und `process.env`. Runtimes mit `fetch` funktionieren, nachdem Sie `process.env` durch ihre eigene Methode zum Lesen von Secrets ersetzt haben.

### Wie wiederhole ich fehlgeschlagene Aufrufe?

Wiederholen Sie nur `429`, `502` und `504`, mit einer Pause, die sich jedes Mal verdoppelt. Wiederholen Sie niemals `400`, `401` oder `402`. Die [Fehlerseite](https://llmwebsearch.com/de/docs/errors/) erklärt warum und zeigt einen Helper.

---

LLMWebSearch: LLMWebSearch ist eine Websuch-API für KI-Agenten, die gerankte Ergebnisse mit dem Inhalt der Top-Seiten als Markdown liefert, bezahlt mit Krypto ohne Ausweis-Upload. Vorausbezahlte Credits ab 1,20 $/1K Suchanfragen verfallen nie. Ohne KYC — kein Ausweis, kein Selfie, keine Dokumente. Mit Krypto bezahlen.
