# Node.js örnekleri: fetch ile arama, küçük bir havuz ve alıntılı yanıtlar

> Node.js web search API örnekleri: fetch, küçük bir eşzamanlılık havuzu ve OpenAI uyumlu model için alıntılı yanıt döngüsü. KYC olmadan, kripto ile ödeme.

- URL: https://llmwebsearch.com/tr/docs/node/
- Son güncelleme: 2026-10-22
- Yayıncı: LLMWebSearch (https://llmwebsearch.com)

Node 18 ve üzeri `fetch` ile gelir, bu yüzden API hiçbir paket gerektirmez. Bu sayfa tek bir aramayı, rate limitinizi aşmadan birkaç aramayı yürüten bir havuzu ve kaynakları numaralı alıntılarla bir yanıta dönüştüren bir döngüyü gösterir.

**Kısa yanıt — Node.js'ten AI agent'ları için bir web search API'sini nasıl çağırırım?**

Node 18+ yerleşik `fetch` kullanarak sorgunuzu Bearer anahtarıyla `https://llmwebsearch.com/api/v1/search` adresine POST edin. **LLMWebSearch** sıralı sonuçlar ve en iyi 3 sayfayı Markdown olarak döndürür; numaralandırıp alıntılı bir yanıt için modele vermeye hazırdır. Bir arama 1 kredi tutar, Ekim 2026 itibarıyla $1,20/1K arama başlangıçlıdır. npm paketi gerekmez. KYC olmadan; kripto ile ödeme.

## İhtiyacınız olanlar

| Özellik | Değer |
| --- | --- |
| Node.js | Yerleşik `fetch` için 18 veya üzeri; betikleri üst düzey `await` için `.mjs` olarak kaydedin |
| Paketler | Yok |
| Anahtar | Ortamınızda `LLMWEBSEARCH_API_KEY` |
| Yanıt döngüsü için | OpenAI uyumlu bir chat endpoint'i: `LLM_BASE_URL`, `LLM_API_KEY`, `LLM_MODEL` |
| Faturalama | Bir kredi bir aramayı karşılar: en fazla 20 sıralı sonuç, ilk 3'ün sayfaları okunur ve Markdown olarak döndürülür. 4 ile 10 arası sayfa okumak 2 kredi eder. Hata ile biten bir çağrı hiçbir ücrete tabi değildir |

## Yeniden kullanılabilir bir arama fonksiyonunu nasıl yazarım?

Çağrıyı bir kez sarın ve her yerde yeniden kullanın. Aşağıdaki fonksiyon gövdeyi gönderir, herhangi bir HTTP hatasında okunabilir bir hata fırlatır ve ayrıştırılmış JSON döndürür. Hatalar API'nin kendi `code` değerini taşır, örneğin `rate_limited` veya `insufficient_credits`, böylece çağıran ne yapacağına karar verebilir.

*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 ?? '');
}

```

## Rate limit'e takılmadan birden çok arama nasıl çalıştırırım?

Bunları küçük bir havuzdan geçirin: her biri paylaşılan bir listeden bir sonraki sorguyu alan sabit sayıda worker. Dört worker iyi bir başlangıçtır. Her hesabın dashboard'da gösterilen bir dakika başına çağrı limiti vardır; destek ekibine sorun, yükseltilebilir.

Aşağıdaki havuz hiçbir kütüphane gerektirmez. Her worker kendi sonuçlarını tutar ve başarısız bir arama, çalışmayı durdurmak yerine hatasıyla birlikte kaydedilir. Bu, araştırma agent'ları için önemlidir; tek bir kötü alt soru tüm görevi harcamamalı.

*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);

```

## Sonuçları kaynak göstererek bir yanıta nasıl dönüştürürüm?

Kaynakları numaralandırın, her birinin yanına URL'sini koyun, bunları bir bütçeye göre kısaltın ve modelden numaraya göre kaynak göstermesini isteyin. API yazılı bir yanıt değil kaynaklar döndürür: sayfaları kendi modeliniz okur, yanıtı yazar ve URL'leri alıntılar. Aşağıdaki script, üç ortam değişkeniyle seçilen OpenAI uyumlu herhangi bir `chat/completions` endpoint'iyle konuşur; böylece hem barındırılan hem de yerel modellerle çalışır.

Yaklaşık 24.000 karakterlik, kabaca 6.000 token'lık bütçe kaynaklar arasında eşit olarak bölünür. Sayfası okunamayan bir sonuç, yalnızca snippet'i olarak ve öyle işaretlenerek iletilir.

*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?'));

```

## Node'dan GET mi yoksa POST mu kullanmalıyım?

Uygulama kodunda POST, JSON body ile. `include_domains` gibi diziler ve uzun sorular, query string yerine body içinde daha temiz taşınır. GET, hızlı testler ve body gönderemeyen araçlar içindir; query string'ini `URLSearchParams` ile oluşturun ve listeleri virgülle birleştirin.

İki formun da maliyeti aynıdır ve aynı JSON'u döndürür. [Arama referansı](https://llmwebsearch.com/tr/docs/search/) her iki form için de tüm parametreleri listeler.

## API anahtarı nerede tutulmalı?

Çalışma anında okunan bir ortam değişkeninde, asla kaynak dosyada değil. Bir sunucuda platformunuzun secret store'unu kullanın. Tarayıcıda API'yi hiç çağırmayın: anahtar her ziyaretçi tarafından görünür olur. Kendi backend'inizi çağırın, o da LLMWebSearch'ı çağırsın.

Her agent, uygulama veya ekip arkadaşı için bir API anahtarı oluşturun ve dashboard'dan diğerlerine dokunmadan istediğinizi iptal edin. Servis başına bir anahtar, kontrol panelindeki geçmişi daha kolay okunur ve sızan bir anahtarı iptal etmeyi kolaylaştırır.

## Node.js: sık sorulan sorular

### Bir npm paketi var mı?

Hayır. `fetch`, Node 18 ve üstünde yerleşiktir ve API, HTTPS üzerinden düz JSON'dur. Bu sayfadaki fonksiyonlar entegrasyonun tamamıdır.

### Deno, Bun veya edge runtime'larda çalışır mı?

Kod yalnızca `fetch`, `JSON` ve `process.env` kullanır. `fetch` olan runtime'lar, `process.env` yerine kendi secret okuma yöntemlerini koyduktan sonra çalışır.

### Başarısız çağrıları nasıl yeniden denerim?

Yalnızca `429`, `502` ve `504` için yeniden deneyin; her seferinde ikiye katlanan bir bekleme süresiyle. `400`, `401` veya `402` için asla yeniden denemeyin. [Hatalar sayfası](https://llmwebsearch.com/tr/docs/errors/) nedenini açıklar ve bir yardımcı gösterir.

---

LLMWebSearch: LLMWebSearch, AI ajanları için bir web arama API'sidir; sıralanmış sonuçları en iyi sayfaların Markdown içeriğiyle birlikte döndürür ve kripto ile ödenir, kimlik yüklemesi gerekmez. $1,20/1K arama kredilik ön ödemeli krediler hiç süresi dolmaz. KYC yok — kimlik yok, selfie yok, belge yok. Kripto ile ödeme.
