Skip to content
CrawlerData
Menu
Integration · AI frameworks

Google Search and Google Shopping tools for LangChain

Two small LangChain tools give your agent fresh Google results and Google Shopping prices. Each one makes a live CrawlerData request and returns a trimmed result that fits in the context window.

Code on this page tested 2026-10-13

Use cases

What you can do

  • Let an agent search Google before it answers, and cite the URLs it used.
  • Answer shopping questions with current prices, merchants and Google Shopping product IDs.
  • Reuse the same functions in LlamaIndex or any framework that takes a Python function or an OpenAI-style tool schema.
Before you start

Prerequisites

  • Python 3.10 or newer.
  • pip install "langchain-core==1.6.10" "requests==2.34.2" (the versions we tested).
  • A CrawlerData API key in the CRAWLERDATA_API_KEY environment variable.
  • A chat model that supports tool calling, from any provider LangChain supports.

No key yet? Sign up for 50 free credits, then create a key under API Access.

Setup

Step by step

  1. Define the tools

    The @tool decorator from langchain_core.tools turns a typed, documented function into a tool. parse_docstring=True copies the Args section into the parameter descriptions the model sees.

    Each tool makes one live request and returns only the fields a model needs: the top 5 organic results, or the top 10 products. Raw responses also include ads, People Also Ask, AI Overview text and more, which you can add if your agent uses them.

    crawlerdata_tools.py
    """LangChain tools for Google Search and Google Shopping via CrawlerData.
    pip install "langchain-core==1.6.10" "requests==2.34.2"
    """
    import os
    
    import requests
    from langchain_core.tools import tool
    
    API_URL = "https://api.crawlerdata.com/v1/jobs"
    HEADERS = {"Authorization": f"Bearer {os.environ['CRAWLERDATA_API_KEY']}"}
    
    
    def _live(endpoint: str, params: dict) -> dict:
        resp = requests.post(API_URL, headers=HEADERS, timeout=200,
                             json={"endpoint": endpoint, "params": params, "queue": "live"})
        resp.raise_for_status()
        data = resp.json()
        if data["job"]["status"] != "completed":
            raise RuntimeError(data["job"]["error"])
        return data["result"]
    
    
    @tool(parse_docstring=True)
    def google_search(query: str, country: str = "us") -> list[dict]:
        """Search Google and return the top organic results (title, url, snippet).
        Use it for current facts, news or anything you are not sure about.
    
        Args:
            query: The search query, as you would type it into Google.
            country: 2-letter country code such as us, gb or de.
        """
        result = _live("google-search", {"query": query, "country": country})
        return [{"title": r["title"], "url": r["link"], "snippet": r.get("snippet")}
                for r in result["organic_results"][:5]]
    
    
    @tool(parse_docstring=True)
    def google_shopping_search(query: str, country: str = "us") -> list[dict]:
        """Search Google Shopping and return products with price, merchant and product_id.
    
        Args:
            query: Product search, e.g. "sony wh-1000xm5".
            country: 2-letter country code such as us, gb or de.
        """
        result = _live("google-shopping-search", {"query": query, "country": country})
        return [{"title": p["title"], "price": p["price"]["raw"] if p.get("price") else None,
                 "merchant": p.get("merchant"), "product_id": p["product_id"]}
                for p in result["shopping_results"][:10]]
  2. Call them and inspect the schema

    Tools can be invoked directly, which is the quickest test. convert_to_openai_tool shows the JSON schema a model receives, with the docstring as the description.

    lc_usage.py
    from langchain_core.utils.function_calling import convert_to_openai_tool
    
    from crawlerdata_tools import google_search, google_shopping_search
    
    # Call a tool directly, the way an agent would.
    print(google_search.invoke({"query": "langchain tool decorator"})[0])
    print(google_shopping_search.invoke({"query": "sony wh-1000xm5", "country": "us"})[:2])
    
    # The JSON schema the model sees (OpenAI function-calling format).
    print(convert_to_openai_tool(google_search))
  3. Give them to your agent

    Pass tools=[google_search, google_shopping_search] to your agent, for example langchain.agents.create_agent(model, tools=[...]), or bind them to a chat model with model.bind_tools([...]). The tools work the same with any tool-calling model.

    A live search usually returns in a few seconds. Let tool calls run for up to about 200 seconds in your agent runtime, matching the client timeout.

  4. Optional: LlamaIndex

    The function behind each LangChain tool is available as .func, so LlamaIndex can wrap it with FunctionTool.from_defaults. We tested this with llama-index-core 0.14.25.

    llamaindex.py
    # pip install "llama-index-core==0.14.25"
    from llama_index.core.tools import FunctionTool
    
    from crawlerdata_tools import google_search
    
    search_tool = FunctionTool.from_defaults(
        fn=google_search.func,  # the plain Python function behind the LangChain tool
        name="google_search",
        description="Search Google and return the top results with title, url and snippet.",
    )
Tested 2026-10-13

How we tested it

  • Ran lc_usage.py with langchain-core 1.6.10 and requests 2.34.2 on Python 3.14: google_search returned 5 results (first: the LangChain tools docs), google_shopping_search returned 10 products with prices and product IDs, and convert_to_openai_tool printed the schema with parameter descriptions. 2 credits.
  • Built the LlamaIndex FunctionTool with llama-index-core 0.14.25 and checked its schema has query and country. It makes no request until called.
Credits

What it costs

Each tool call is 1 credit. An agent that searches twice to answer a question uses 2 credits.

Cache results by query and country for a few hours if your agent repeats searches; a cache hit costs nothing.

See credit pack prices →

Troubleshooting

If something goes wrong

401 INVALID_API_KEY
The key is missing, mistyped or revoked. Send it as "Authorization: Bearer YOUR_API_KEY" (with the word Bearer and one space) and check the key is active under API Access in the dashboard.
KeyError: CRAWLERDATA_API_KEY
The module reads the key when it is imported. Export the variable before starting Python, or load your .env file first.
402 INSUFFICIENT_CREDITS
Your balance is too low for the request. Buy a credit pack in the dashboard. Requests that fail for other reasons are not charged, so a 402 never costs credits.
429 RATE_LIMITED
Each API key allows 100 requests per minute and 20 per second. Wait until the time in the X-RateLimit-Reset header (a Unix timestamp) and retry, or spread requests out.
Timeouts on live requests
A live request returns when the result is ready. Search requests usually take a few seconds; a Google Shopping sellers request collects every seller for the product, so allow more time. Set the client timeout to about 200 seconds, or use the fast queue and poll the job.
RuntimeError from the tool
The job failed, and the message is job.error. It cost 0 credits. Many agent frameworks pass tool errors back to the model, which can retry with a different query.

Request and response schemas: OpenAPI 3.1 document. Still stuck? Email contact@crawlerdata.com.

FAQ

Questions

Do I need a LangChain integration package?

No. The tools on this page are about 40 lines of Python that you own, so you control which fields reach the model.

Why not return the whole JSON response?

A full Google results page has many sections the model does not need, and every token costs money and context space. Return the fields your agent uses.

Can the agent get every seller for a product?

Yes. Add a third tool that calls the google-shopping-product endpoint with a product_id from google_shopping_search. It returns every seller in one call, at 1 credit per 10 sellers returned; give it the same generous timeout.

Should I use the MCP server instead?

If your framework supports MCP clients, you can connect to the CrawlerData MCP server and get all eight tools without writing them. Use these Python tools when you want to control the output format.

Try it with 50 free credits

Sign up with your work email and verify it, then create an API key. Failed requests are never charged.

Get 50 free credits