Back to use cases

    Use case / DEVELOPERS / Python 3 / Published

    Web Search API Quickstart: Add Web Search to Your App in Python

    Add web search to your own app with one GET call and a tiny JSON service that returns clean title, url, snippet and domain results, with paging and a cache.

    Card for Web Search API Quickstart: Add Web Search to Your App in Python

    This web search API quickstart is for developers who want web search results inside their own app without building a crawler. Make one GET /web call, then wrap it in a tiny JSON service with one route, GET /search?q=, that returns clean {title, url, snippet, domain} results. It uses only the Python standard library, with Python and JavaScript snippets to start from.

    The problem

    Many apps need a search box that looks at the web: a research tool, an agent, a link finder in a CMS. Building and running a crawler for that is a project of its own. What most teams want is one call that returns titles, links and snippets, plus a clear price per call. Then they need the small pieces around it: input checks, paging, removing duplicate links and caching.

    What the search API quickstart does

    • One route, GET /search?q=, with q from 1 to 300 characters and pages from 1 to 3.
    • Returns results as {title, url, snippet, domain, rank}.
    • Removes duplicate URLs (same host without www, same path) and counts them in repeats_dropped.
    • Caches each query for 10 minutes, so the same search again is free and instant.
    • Rejects bad requests with HTTP 400 before any call.
    • Includes a small HTML search page and a CLI.

    How it works

    1. Check the query. Not blank, at most 300 characters, pages 1 to 3.
    2. Search the web. GET /web with query and start. Page 1 is start=0, page 2 is start=20, page 3 is start=40.
    3. Clean up. Turn each result into {title, url, snippet, domain, rank} and drop repeated URLs.
    4. Cache and serve. Store the result for 10 minutes and return JSON with the count, cost and latency.

    The code

    The core call, copied from the example's README. The key is read from the DESEARCH_API_KEY env var:

    PYTHON
    import json, os, urllib.parse, urllib.request
    url = "https://api.desearch.ai/web?" + urllib.parse.urlencode({"query": "bittensor subnet", "start": 0})
    req = urllib.request.Request(url, headers={"Authorization": os.environ["DESEARCH_API_KEY"]})
    with urllib.request.urlopen(req, timeout=60) as r:
        print(r.headers.get("X-Desearch-Cost-Usd"))
        for item in json.load(r)["data"]:
            print(item["title"], item["link"])

    The response holds data, a list of results with title, link and snippet. The README also has the same call in curl and in JavaScript.

    The folder layout:

    • core.py: query check, paging, result cleanup, dedupe, cache and HTML. No network.
    • app.py: the HTTP service, the CLI and the Desearch client.
    • test_core.py: offline tests.
    • samples/: one /search response and the matching HTML page.

    Endpoints

    • GET /web

    Example output

    Saved sample from a run on 2026-10-16 at 15:14 (Asia/Tbilisi) for GET /search?q=bittensor+subnet&pages=2. This page shows that stored request and response. It does not run a live demo.

    Sample request

    GET /search?q=bittensor+subnet&pages=2

    That service call runs two GET /web requests. Page 1 is start=0 and page 2 is start=20.

    Sample response

    What came backCount
    Desearch calls2
    Results per page19 and 20
    Repeated URLs dropped2
    Results returned37
    Time for both calls8.87 s
    Same request from the cacheabout 2 ms, 0 calls

    Two of the first results, trimmed:

    JSON
    {"rank": 3, "domain": "bittensor.com", "title": "Running a subnet - Bittensor Docs", "url": "https://www.bittensor.com/docs/guides/subnets"}
    {"rank": 5, "domain": "docs.learnbittensor.org", "title": "Subnet Configuration (Hyperparameters) | Bittensor", "url": "https://docs.learnbittensor.org/subnets/subnet-hyperparameters"}

    Run it yourself

    BASH
    git clone https://github.com/Desearch-ai/desearch-py-examples && cd desearch-py-examples/web-search-api-quickstart
    export DESEARCH_API_KEY=...   # from console.desearch.ai
    python3 app.py --port 8000    # then: curl -s "http://127.0.0.1:8000/search?q=bittensor+subnet&pages=2"
    • pages: 1 to 3 pages of results, one call each.
    • --cli "bittensor subnet" --pages 2: run one search from the command line.
    • --log-dir runs/today: save each API call with the key removed.

    What it costs

    Measured on 2026-10-16 from the X-Desearch-Cost-Usd header: $0.001 per GET /web call, whatever the number of results. One page is one call, so pages=2 is $0.002, and a cache hit is $0. See pricing.

    Ideas to extend it

    • Put the /search route behind your app's search box or give it to an agent as a tool.
    • Add domain filters in your service to show results from sites you choose.
    • Store results per query to build a small research archive over time.

    Use with AI agents

    Point an MCP client at the hosted Desearch server. Replace the placeholder with a key from the console. Do not commit the key.

    JSON
    {
      "mcpServers": {
        "desearch": {
          "url": "https://mcp.desearch.ai/mcp",
          "headers": {
            "Authorization": "Bearer <DESEARCH_API_KEY>"
          }
        }
      }
    }

    Prompt you can paste for this example:

    Use Desearch GET /web for the query I give you. Return the title, link and snippet for each result. Page with start 0, then 20, then 40. Drop duplicate URLs. Do not invent results.

    Build your own example.

    Give your agents access to web and social search. Get an API key to start building, or talk to us about your integration.

    Read docs