npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

google-custom-search-api-client

v1.3.1

Published

A production-ready, highly resilient Node.js client for the Google Custom Search JSON API with built-in rate limiting and exponential backoff.

Readme

npm version License: MIT Node.js CI PRs Welcome


💡 Why this library? (Competitive Analysis)

If you need Google Search results in Node.js, you usually face a dilemma. Here is how this library compares to the alternatives:

  1. vs. The Official googleapis Package

    • The Problem: The official SDK is massively bloated (megabytes in size) because it includes clients for every Google service (Drive, Cloud, YouTube, etc.).
    • Our Solution: This library is Zero-Dependency (uses native https). It's incredibly lightweight, lightning-fast, and focused only on search.
  2. vs. Scraping (Puppeteer / Cheerio / google-it)

    • The Problem: Scraping Google directly results in CAPTCHAs, IP bans, and broken code every time Google updates their DOM. You are forced to buy expensive rotating proxies.
    • Our Solution: We use the Official Google JSON API. It is 100% legal, requires no proxies, never triggers CAPTCHAs, and returns clean, structured JSON.
  3. vs. Paid SERP APIs (SerpApi, Serper, DataForSEO)

    • The Problem: Middleman APIs charge a massive premium for scraping Google on your behalf.
    • Our Solution: Cut out the middleman. By hitting Google's API directly, you get 100 free queries a day, and after that, it's just $5 per 1,000 queries—far cheaper than third-party API limits.
  4. vs. End-User AI Tools (ChatGPT, Perplexity, etc.)

    • The Problem: Generative AI tools are incredible for conversational answers, but they are terrible for programmatic infrastructure. They hallucinate data, return unstructured text that breaks your parsers, and cost dollars instead of cents when fetching data at scale. Most importantly, AI models inherently cannot search the web without an underlying search tool.
    • Our Solution: We are the pickaxe in the AI gold rush. This library provides deterministic, structured JSON with lightning-fast ~200ms latency. We provide the foundational ground-truth data that AI agents need to function. By using our built-in MCP and LangChain bindings, you can use this library to build the next Perplexity.

But we didn't stop there. Even if you use Google's official endpoints, you still have to build resilience. This library handles the heavy lifting for you natively:

  • Smart Rate Limiting: Built-in delays during pagination prevent you from hitting Google's strict quota limits (429 errors).
  • Enterprise-Grade Resilience: Uses Exponential Backoff with Jitter to smoothly handle transient 5xx errors and timeouts.
  • Developer Experience (DX): Fully documented with JSDoc types for deep IDE autocomplete and IntelliSense support.
  • Custom Error Handling: Differentiates between Quota Exceeded (403), Bad Request (400), and Network timeouts natively.

🚀 Installation

npm install google-custom-search-api-client
# or
yarn add google-custom-search-api-client

(Note: Ensure you are using Node.js 14+)

🔑 Setup & Authentication

To use this API, you need two things from Google:

  1. API Key: Generate one from the Google Cloud Console.
  2. Search Engine ID (CX): Create your engine at the Programmable Search Engine control panel.

Set them in your environment variables (e.g., using .env):

GOOGLE_API_KEY=AIzaSyYourApiKeyHere...
GOOGLE_CX=your_search_engine_id

📖 Usage Examples

1. Basic Web Search

import GoogleSearchAPI from "google-custom-search-api-client";
import dotenv from "dotenv";
dotenv.config();

const searchAPI = new GoogleSearchAPI(
  process.env.GOOGLE_API_KEY,
  process.env.GOOGLE_CX,
  { timeout: 10000 }, // Optional: set request timeout
);

try {
  const results = await searchAPI.search("Node.js backend tutorials", {
    num: 10, // Results per request (max 10)
    start: 1, // Start index (1-based)
    gl: "us", // Geolocation
    hl: "en", // Language
  });

  console.log(`Found ${results.searchInformation.totalResults} results!`);
  results.items.forEach((item) => console.log(item.title, item.link));
} catch (err) {
  console.error("Search failed:", err.message);
}

2. Auto-Pagination (Fetching 100+ results safely)

Google limits requests to 10 results at a time. The searchWithPagination method automatically handles multiple requests, respects rate limits, and merges the results.

// Fetches 30 results total, automatically waiting 500ms between requests to avoid 429s.
const allResults = await searchAPI.searchWithPagination("Latest AI news", {
  totalResults: 30,
  resultsPerPage: 10,
  delayMs: 500, // ⏳ Built-in rate limiting protection
});

console.log(`Successfully fetched ${allResults.length} items.`);

3. Image Search

Easily toggle into image search mode to scrape image URLs.

const images = await searchAPI.search("cute puppies", {
  num: 5,
  searchType: "image",
});

images.items.forEach((img) => console.log(img.link));

4. Command Line Interface (CLI)

You can perform searches directly from your terminal!

# Basic search
npx google-custom-search-api-client "Node.js tutorial" -n 5

# Image search
npx google-custom-search-api-client "cute puppies" -i -n 3

Note: Ensure GOOGLE_API_KEY and GOOGLE_CX are set in your .env file or exported to your terminal.

🛠 Advanced Features

Corporate Proxies & Custom Fetch Options

Because we use the native fetch API, you can easily pass custom fetchOptions to support internal corporate proxies (e.g. undici proxy dispatchers).

import { ProxyAgent } from "undici";

const searchAPI = new GoogleSearchAPI(API_KEY, CX, {
  fetchOptions: {
    dispatcher: new ProxyAgent("http://your-corporate-proxy:8080"),
  },
});

Robust Error Handling

Catch specific HTTP errors directly via the GoogleSearchAPIError class:

import { GoogleSearchAPIError } from "google-custom-search-api-client";

try {
  await searchAPI.search("test");
} catch (error) {
  if (error instanceof GoogleSearchAPIError) {
    if (error.statusCode === 403)
      console.error("Quota Exceeded or Invalid API Key");
    if (error.statusCode === 400)
      console.error("Invalid Search Engine ID (CX)");
  }
}

🤖 AI Agent Integrations (MCP & LangChain)

We natively support the Model Context Protocol (MCP) and LangChain out of the box!

For MCP (Claude Desktop, Cursor, etc.): You can run this library as a standalone MCP server to give your AI assistants live internet access.

# Add this to your claude_desktop_config.json
"google-search": {
  "command": "npx",
  "args": ["-y", "google-custom-search-api-client", "google-search-mcp"],
  "env": {
    "GOOGLE_API_KEY": "your_api_key",
    "GOOGLE_CX": "your_cx_id"
  }
}

For LangChain JS: Easily bind our search tool to your autonomous agents.

import { createGoogleSearchTool } from "google-custom-search-api-client/langchain";

const searchTool = createGoogleSearchTool(
  process.env.GOOGLE_API_KEY,
  process.env.GOOGLE_CX,
);

// Bind to your LLM agent
const agent = model.bindTools([searchTool]);

📊 Google API Limits (Important)

Keep these Google limits in mind when scaling your application:

  • Free tier: 100 queries/day.
  • Paid tier: $5 per 1,000 queries (maximum 10,000/day).
  • Max results per query: 10.
  • Deep pagination limit: Google restricts programmatic access to the first 100 results (start + num ≤ 101).

🗺️ Roadmap

Phase 1 Complete: We now fully support Edge Runtimes (Cloudflare Workers/Next.js via native fetch) and have launched the CLI tool! ✅ Phase 3 Complete: We now natively export an MCP Server and LangChain JS Tools! Curious about what's next? We are planning a Caching layer and a Native TypeScript migration. Check out our ROADMAP.md for the full iteration plan!

🤝 Contributing

Contributions, issues, and feature requests are welcome! Feel free to check the issues page.

📝 License

This project is MIT licensed.


Keywords for search visibility: Google Custom Search API, Google Search Node.js, CSE Client, Programmable Search Engine Node.js, SERP Scraping API, Google Image Search Node, Exponential Backoff, Rate Limiting Search API.