From serpapi-pack
Provides SerpApi client patterns with TypeScript result interfaces, LRU response caching, and Python multi-engine abstraction for search services.
How this skill is triggered — by the user, by Claude, or both
Slash command
/serpapi-pack:serpapi-sdk-patternsThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Production patterns for SerpApi: typed result interfaces, response caching (critical since each search costs credits), multi-engine abstraction, and async search with the Searches Archive API.
Production patterns for SerpApi: typed result interfaces, response caching (critical since each search costs credits), multi-engine abstraction, and async search with the Searches Archive API.
interface SerpApiOrganicResult {
position: number;
title: string;
link: string;
snippet: string;
displayed_link: string;
source?: string;
}
interface SerpApiSearchResult {
search_metadata: { id: string; status: string; created_at: string };
search_parameters: Record<string, string>;
organic_results: SerpApiOrganicResult[];
answer_box?: { answer?: string; snippet?: string; title?: string };
knowledge_graph?: { title: string; description?: string; type?: string };
related_questions?: Array<{ question: string; snippet: string }>;
pagination?: { next: string };
}
import { getJson } from 'serpapi';
import { LRUCache } from 'lru-cache';
const cache = new LRUCache<string, SerpApiSearchResult>({
max: 500,
ttl: 3600_000, // 1 hour -- search results are relatively stable
});
async function cachedSearch(params: Record<string, any>): Promise<SerpApiSearchResult> {
const key = JSON.stringify(params);
const cached = cache.get(key);
if (cached) return cached;
const result = await getJson({
...params,
api_key: process.env.SERPAPI_API_KEY,
}) as SerpApiSearchResult;
cache.set(key, result);
return result;
}
import serpapi, os
class SearchService:
ENGINES = {
"web": {"engine": "google", "query_param": "q"},
"news": {"engine": "google_news", "query_param": "q"},
"images": {"engine": "google_images", "query_param": "q"},
"youtube": {"engine": "youtube", "query_param": "search_query"},
"bing": {"engine": "bing", "query_param": "q"},
"shopping": {"engine": "google_shopping", "query_param": "q"},
}
def __init__(self):
self.client = serpapi.Client(api_key=os.environ["SERPAPI_API_KEY"])
def search(self, query: str, engine: str = "web", **kwargs) -> dict:
config = self.ENGINES[engine]
params = {
"engine": config["engine"],
config["query_param"]: query,
**kwargs,
}
return self.client.search(**params)
# Usage
svc = SearchService()
web = svc.search("Claude AI")
news = svc.search("Claude AI", engine="news")
videos = svc.search("Claude AI tutorial", engine="youtube")
# Submit search asynchronously -- retrieve later
result = client.search(engine="google", q="expensive query", async_search=True)
search_id = result["search_metadata"]["id"]
# Later: retrieve from archive (no extra credit charge)
import time
while True:
archived = client.search(engine="google", search_id=search_id)
if archived["search_metadata"]["status"] == "Success":
break
time.sleep(2)
| Pattern | Use Case | Benefit |
|---|---|---|
| LRU cache | Repeated queries | Saves API credits |
| Engine abstraction | Multi-engine | Clean API for consumers |
| Async search | Heavy queries | Non-blocking, same credit cost |
| Type interfaces | All usage | Catch response changes early |
Apply patterns in serpapi-core-workflow-a for real-world usage.
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin serpapi-packProvides production reference architecture for SerpApi search services with caching, multi-engine abstraction, SERP tracking, and monitoring using TypeScript, Redis, and PostgreSQL.
Automates Serpapi operations via Composio's Serpapi toolkit through Rube MCP. Always searches for current tool schemas before execution.
Searches the web via Bright Data CLI: `bdata search` for Google/Bing/Yandex SERP results, `bdata discover` for intent-ranked semantic discovery with optional page content. Hands off to `scrape` or `data-feeds` when appropriate.