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.
Maintainers
Readme
💡 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:
vs. The Official
googleapisPackage- 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.
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.
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.
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:
- API Key: Generate one from the Google Cloud Console.
- 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 3Note: 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.
