ไม่ต้อง KYC — ไม่ต้องใช้บัตรประชาชน ไม่ต้องเซลฟี่ ไม่ต้องใช้เอกสาร จ่ายด้วยคริปโต: BTC, USDT, USDC, ETH, SOL, LTC
ภาษา: ไทย
รับ API key

Docs · Node.js 18+ · fetch · ESM

SERP API ใน Node.js: fetch, worker pool และ pagination

ไม่ต้องมี dependency: Node.js มี fetch ตั้งแต่เวอร์ชัน 18 เป็นต้นมา ไคลเอนต์เล็ก ๆ พร้อม JSDoc type สำหรับ editor และ TypeScript, pool ที่เคารพขีดจำกัดของบัญชีคุณ และลูป pagination ที่หยุดเมื่อผลลัพธ์หมด

อัปเดตล่าสุด: · 3 นาทีในการอ่าน

คำตอบสั้น

ฉันใช้ SERP API ใน Node.js ได้อย่างไร?

เรียก fetch("https://serpcrypto.com/api/v1/search?" + new URLSearchParams({ q })) พร้อม header Authorization: Bearer <key> แล้วอ่าน await res.json() Node.js 18+ ไม่ต้องใช้แพ็กเกจ SerpCrypto คืนผลการค้นหา Google หรือ Bing เป็น JSON ในราคา 1 เครดิตต่อการค้นหาที่สำเร็จ เริ่มต้นที่ US$0.30/1K การค้นหา และไม่เรียกเก็บเงินเมื่อเกิดข้อผิดพลาด จ่ายด้วยคริปโต ไม่ต้อง KYC

การตั้งค่า Node.js โดยสรุป

RuntimeNode.js 18 หรือใหม่กว่า (มี fetch, AbortSignal.timeout ในตัว)
โมดูลES modules: ไฟล์ .mjs หรือ "type": "module" ใน package.json
คีย์process.env.SERPCRYPTO_API_KEY
Timeout90 วินาทีด้วย AbortSignal.timeout(90_000)
การค้นหาแบบขนานพูลที่ปรับขนาดให้เท่ากับ concurrency_limit
TypesJSDoc typedefs ที่ VS Code และ tsc --checkJs อ่านได้

จะเขียนไคลเอนต์แบบ typed ขนาดเล็กได้อย่างไร?

รวม endpoint, header และการจัดการข้อผิดพลาดไว้ในโมดูลเดียว บรรทัด JSDoc @typedef อธิบายคำตอบ ดังนั้นเอดิเตอร์จะเติม organic_results อัตโนมัติและตรวจ type ของโค้ดคุณได้โดยไม่ต้องมีขั้นตอน build ผู้ใช้ TypeScript สามารถคัดลอก shape เดียวกันไปไว้ใน interface ได้

ฟังก์ชัน search จะ throw Error พร้อม HTTP status และ code ข้อผิดพลาดของ API ไว้ในข้อความ จากนั้นโค้ดของคุณจะตัดสินใจได้ว่าจะ retry 429, 502 และ 504 และหยุดเมื่อเจอข้อผิดพลาดอื่น ตามที่อธิบายไว้ใน หน้าข้อผิดพลาด

serp-client.mjs
// serp-client.mjs — Node.js 18+, no dependency
const API_URL = "https://serpcrypto.com/api/v1/search";
const CREDITS_URL = "https://serpcrypto.com/api/v1/credits";
const headers = { Authorization: `Bearer ${process.env.SERPCRYPTO_API_KEY}` };

/**
 * @typedef {Object} OrganicResult
 * @property {number} position
 * @property {string} title
 * @property {string} link
 * @property {string} [snippet]
 * @property {string} [date]
 */

/**
 * @typedef {Object} SearchResponse
 * @property {Object} search_metadata
 * @property {string} search_metadata.id
 * @property {string} search_metadata.status
 * @property {number} search_metadata.credits_used
 * @property {OrganicResult[]} [organic_results]
 * @property {Object} [pagination]
 * @property {number} pagination.current
 * @property {number} [pagination.next_page]
 */

/**
 * Run one search (1 credit when it succeeds).
 * @param {string} q
 * @param {Record<string, string | number>} [params]
 * @returns {Promise<SearchResponse>}
 */
export async function search(q, params = {}) {
  const query = new URLSearchParams({ q, ...Object.fromEntries(Object.entries(params).map(([k, v]) => [k, String(v)])) });
  const res = await fetch(`${API_URL}?${query}`, { headers, signal: AbortSignal.timeout(90_000) });
  if (!res.ok) {
    const body = await res.json().catch(() => ({}));
    const err = new Error(`${res.status} ${body.error?.code ?? "error"}: ${body.error?.message ?? ""}`);
    err.status = res.status;
    throw err;
  }
  return res.json();
}

/** Free: credits left, used today and the concurrency limit. */
export async function credits() {
  const res = await fetch(CREDITS_URL, { headers });
  if (!res.ok) throw new Error(`credits: HTTP ${res.status}`);
  return res.json();
}

จะรันการค้นหาแบบขนานโดยไม่เจอ 429 ได้อย่างไร?

เริ่มจำนวน worker เท่าที่บัญชีของคุณอนุญาต และให้แต่ละตัวดึงคำค้นหาถัดไปจากลิสต์ที่แชร์กัน พูลจะอ่าน concurrency_limit จาก endpoint เครดิตฟรี จึงไม่ส่งการค้นหาพร้อมกันมากกว่าที่บัญชีรับได้

คำค้นหาที่ล้มเหลวจะถูกบันทึกไว้ แล้ว worker ก็ไปต่อ รันคำที่ล้มเหลวอีกครั้งภายหลัง: ข้อผิดพลาดไม่มีค่าใช้จ่าย ดังนั้นรอบที่สองจึงฟรีจนกว่าจะสำเร็จ

batch.mjs: พูลของ worker
// batch.mjs — parallel searches, never more than the account's limit at once
import { search, credits } from "./serp-client.mjs";

const keywords = ["password manager", "note taking app", "time tracking software", "invoice software"];
const { concurrency_limit: limit } = await credits();

let next = 0;
const results = new Map();

async function worker() {
  while (next < keywords.length) {
    const kw = keywords[next++];
    try {
      const data = await search(kw, { gl: "us", hl: "en" });
      results.set(kw, data.organic_results?.[0]?.link ?? null);
    } catch (err) {
      results.set(kw, `failed: ${err.message}`);
    }
  }
}

await Promise.all(Array.from({ length: Math.min(limit, keywords.length) }, worker));
console.table(Object.fromEntries(results));

จะดึงผลลัพธ์หลายหน้าได้อย่างไร?

วนซ้ำบน page และหยุดทันทีที่ pagination.next_page หายไป ผลลัพธ์ออร์แกนิกประมาณ 10 รายการต่อหน้า ตามที่ Google ให้บริการตั้งแต่เลิกใช้ num=100 ในเดือนกันยายน 2025; แต่ละหน้าเพิ่มคือหนึ่งเครดิตเพิ่มเติม การตรวจหนึ่งคำค้นหาสามหน้าเสียสามเครดิต คำค้นหาที่มีผลลัพธ์เพียงหน้าเดียวเสียหนึ่งเครดิต

pages.mjs
// pages.mjs — up to three pages, stop when results end
import { search } from "./serp-client.mjs";

async function topResults(q, pages = 3, params = {}) {
  const rows = [];
  for (let page = 1; page <= pages; page++) {
    const data = await search(q, { ...params, page });
    for (const r of data.organic_results ?? []) rows.push({ page, position: r.position, link: r.link });
    if (!data.pagination?.next_page) break; // nothing more: save the credits
  }
  return rows;
}

console.log(await topResults("headless cms", 3, { gl: "de", hl: "en" }));

เรียก API จากเบราว์เซอร์หรือ edge function ได้ไหม?

จากเซิร์ฟเวอร์หรือ edge function ได้: Cloudflare Workers, Vercel และ Deno ให้ fetch แบบเดียวกันทั้งหมด จากหน้าเบราว์เซอร์ ทำไม่ได้: key จะมองเห็นได้โดยผู้เข้าชมทุกคน ให้วาง route เล็กๆ บนเซิร์ฟเวอร์คั่นกลางที่เก็บ key ไว้และส่งต่อเฉพาะพารามิเตอร์ที่คุณอนุญาต

กฎเดียวกันใช้กับแอปมือถือ ทุกอย่างที่ส่งไปยังอุปกรณ์ของผู้ใช้สามารถถูกอ่านได้ ดังนั้น key จึงต้องอยู่บนเซิร์ฟเวอร์ของคุณ

จะควบคุมค่าใช้จ่ายใน Node.js ให้คาดเดาได้อย่างไร?

นับจำนวนการเรียกที่คุณทำ: การเรียกที่สำเร็จหนึ่งครั้งคือหนึ่งเครดิต ที่ US$0.56/1K การค้นหา บนแพ็ก 100,000 การค้นหา ตรวจ credits_remaining ก่อนเริ่มแบตช์ใหญ่ และหยุดพูลเมื่อใกล้ศูนย์แทนที่จะเก็บคำตอบ 402 ติดกันหลายอัน เครดิตการค้นหาแบบเติมเงินไม่มีวันหมดอายุ: คำค้นหาที่ไม่ได้ใช้จะคงอยู่ในบัญชีของคุณจนกว่าคุณจะใช้ ส่วนที่เหลือที่ยังไม่ได้ใช้จึงเก็บไว้สำหรับงานถัดไป

คำถามเกี่ยวกับ Node.js

มีแพ็กเกจ npm สำหรับ SerpCrypto ไหม?

ไม่มี ไคลเอนต์ด้านบนมีขนาดประมาณ 40 บรรทัดของ JavaScript มาตรฐานที่ใช้ fetch จึงไม่มีอะไรของเราที่ต้องติดตั้ง คัดลอกลงในโปรเจกต์ของคุณแล้วปรับใช้ได้เลย

ใช้กับ CommonJS (require) ได้ไหม?

ตัวอย่างใช้ ES modules สำหรับ await ระดับบนสุด ในไฟล์ CommonJS ให้ห่อการเรียกด้วยฟังก์ชัน async และใช้ fetch แบบเดียวกัน; มันเป็น global ใน Node.js 18+

จะใช้กับ TypeScript ได้อย่างไร?

คัดลอก JSDoc shape ไปไว้ใน interface SearchResponse แล้วกำหนด type ของผลลัพธ์จาก res.json() ด้วย shape นั้น บล็อกที่เป็น optional เช่น organic_results? ต้องคงเป็น optional ไว้ เพราะหน้าเว็บอาจไม่แสดงบล็อกเหล่านั้น

ต้องใช้ Node.js เวอร์ชันไหน?

Node.js 18 ขึ้นไปสำหรับ fetch ที่มีมาในตัว AbortSignal.timeout ใช้ได้ตั้งแต่ Node.js 17.3 ดังนั้น 18 ครอบคลุมทุกอย่างในหน้านี้

เริ่มต้นที่ US$0.30/1K การค้นหา · ไม่ต้อง KYC

รับ API key