Skip to main content
POST
https://nano-gpt.com
/
api
/
web
Web Search
curl --request POST \
  --url https://nano-gpt.com/api/web \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <x-api-key>' \
  --data '
{
  "query": "<string>",
  "provider": "<string>",
  "depth": "<string>",
  "outputType": "<string>",
  "structuredOutputSchema": "<string>",
  "includeImages": true,
  "kagiSource": "<string>",
  "fromDate": "<string>",
  "toDate": "<string>",
  "excludeDomains": [
    "<string>"
  ],
  "includeDomains": [
    "<string>"
  ]
}
'
{
  "error": "Query parameter is required and must be a string"
}

Overview

The Web Search API allows you to perform AI-powered web searches across supported providers (Linkup, Tavily, Exa, Kagi, Perplexity, Valyu, Brave), returning up-to-date information from across the internet. This API supports multiple output formats, date filtering, domain filtering, and provider-specific depth modes. If provider is omitted, Linkup is used by default.

Authentication

x-api-key
string
required
Your NanoGPT API key
Alternatively, you can use Bearer token authentication:
Authorization
string
Bearer YOUR_API_KEY

Request Body

query
string
required
The search query to send to the provider
provider
string
default:"linkup"
Search provider. Options: “linkup”, “tavily”, “exa”, “kagi”, “perplexity”, “valyu”, “brave”. “openai-native” is not supported on /api/web.
depth
string
default:"standard"
Search depth. Options vary by provider:
  • Linkup/Tavily/Perplexity/Valyu/Brave: “standard” or “deep”
  • Exa: “fast”, “auto”, “neural”, “deep” (Exa-only)
  • Kagi: “standard” or “deep” (“search” source only for deep)
outputType
string
default:"searchResults"
Output format. Options: “searchResults”, “sourcedAnswer”, or “structured”. For Tavily, Exa, Kagi, Perplexity, Valyu, and Brave, outputType must be “searchResults”.
structuredOutputSchema
string
Required when outputType is “structured”. JSON schema string defining the desired response format
includeImages
boolean
default:false
Whether to include image results in the search
kagiSource
string
Kagi only. Source to query: “web”, “news”, or “search” (also accepts “kagi_source”)
fromDate
string
Filter results from this date (YYYY-MM-DD format)
toDate
string
Filter results until this date (YYYY-MM-DD format)
excludeDomains
string[]
Array of domains to exclude from search results
includeDomains
string[]
Array of domains to search exclusively

Provider-specific options

Provider-specific fields are accepted at the top level of the request body and only apply to the selected provider.

Perplexity options

{
  "maxResults": 1-20,
  "maxTokensPerPage": number,
  "maxTokens": 1-1000000,
  "country": "string",
  "searchDomainFilter": ["domain1.com", "domain2.com"],
  "searchLanguageFilter": ["en", "de"]
}
Limits: searchDomainFilter max 20 entries; searchLanguageFilter max 10 entries (ISO 639-1).

Valyu options

{
  "searchType": "all" | "web",
  "fastMode": boolean,
  "maxNumResults": 1-50,
  "maxPrice": number,
  "relevanceThreshold": 0-1,
  "responseLength": "short" | "medium" | "large" | "max" | number,
  "countryCode": "US",
  "includedSources": ["source1.com"],
  "excludedSources": ["source2.com"],
  "urlOnly": boolean,
  "category": "string"
}
countryCode uses a 2-letter ISO country code.

Tavily options

{
  "maxResults": 0-20,
  "includeAnswer": boolean | "basic" | "advanced",
  "includeRawContent": boolean | "markdown" | "text",
  "includeImages": boolean,
  "includeImageDescriptions": boolean,
  "includeFavicon": boolean,
  "topic": "general" | "news" | "finance",
  "timeRange": "day" | "week" | "month" | "year",
  "startDate": "YYYY-MM-DD",
  "endDate": "YYYY-MM-DD",
  "chunksPerSource": 1-3,
  "country": "string"
}

Exa options

{
  "numResults": 1-100,
  "category": "company" | "research paper" | "news" | "pdf" | "github" | "tweet" | "personal site" | "people" | "financial report",
  "userLocation": "US",
  "additionalQueries": ["query2"],
  "startCrawlDate": "ISO 8601",
  "endCrawlDate": "ISO 8601",
  "startPublishedDate": "ISO 8601",
  "endPublishedDate": "ISO 8601",
  "includeText": ["pattern"],
  "excludeText": ["pattern"],
  "livecrawl": "never" | "fallback" | "always" | "preferred",
  "livecrawlTimeout": number,
  "subpages": number,
  "subpageTarget": "string" | ["strings"]
}

Kagi options

{
  "kagiSource": "web" | "news" | "search"
}

Brave options

{
  "count": 0-20,
  "maxResults": 0-20,
  "offset": 0-9,
  "safesearch": "off" | "moderate" | "strict",
  "freshness": "2024-01-01to2024-02-01",
  "searchLang": "string",
  "uiLang": "string",
  "eSnippets": boolean,
  "spellcheck": boolean,
  "goggles": "string" | ["string"],
  "country": "string"
}
Use either count or maxResults (0-20). searchLang and uiLang are passed to Brave as search_lang and ui_lang. If freshness is not provided but both fromDate and toDate are set, the API builds a Brave freshness range (fromDate + "to" + toDate). For deep searches, Brave defaults extraSnippets to true unless eSnippets is explicitly set.

Response

data
object|array
Search results, answer, or structured data depending on outputType
metadata
object

Output Formats

Search Results (default)

Returns an array of search results with text and image entries:
{
  "data": [
    {
      "type": "text",
      "title": "Article Title",
      "url": "https://example.com/article",
      "snippet": "Article snippet...",
      "publishedAt": "2025-07-01"
    },
    {
      "type": "image",
      "title": "Image Title",
      "url": "https://example.com/image.jpg",
      "imageUrl": "https://example.com/image.jpg",
      "publishedAt": "2025-07-01"
    }
  ],
  "metadata": {
    "query": "your search query",
    "provider": "linkup",
    "depth": "standard",
    "outputType": "searchResults",
    "timestamp": "2025-07-08T09:00:00.000Z",
    "cost": 0.006
  }
}

Sourced Answer

Returns a comprehensive answer with source citations:
{
  "data": {
    "answer": "The comprehensive answer to your query...",
    "sources": [
      {
        "name": "Source Name",
        "url": "https://example.com",
        "snippet": "Relevant snippet from the source..."
      }
    ]
  },
  "metadata": {
    "query": "your search query",
    "provider": "linkup",
    "depth": "standard",
    "outputType": "sourcedAnswer",
    "timestamp": "2025-07-08T09:00:00.000Z",
    "cost": 0.006
  }
}

Structured Output

Returns data matching your provided JSON schema:
{
  "data": {
    // Your structured data according to the schema
  },
  "metadata": {
    "query": "your search query",
    "provider": "linkup",
    "depth": "standard",
    "outputType": "structured",
    "timestamp": "2025-07-08T09:00:00.000Z",
    "cost": 0.006
  }
}

Examples

import requests
import json

# Your API key
api_key = "YOUR_API_KEY"

# API endpoint
url = "https://nano-gpt.com/api/web"

# Headers
headers = {
    "Content-Type": "application/json",
    "x-api-key": api_key
}

# Basic search
basic_search = {
    "query": "artificial intelligence trends 2025",
    "provider": "linkup"
}

response = requests.post(url, headers=headers, json=basic_search)
results = response.json()

# Print results
if results["metadata"]["outputType"] == "searchResults":
    for result in results["data"]:
        print(f"Title: {result['title']}")
        print(f"URL: {result['url']}")
        print(f"Snippet: {result.get('snippet', 'N/A')[:200]}...")
        print("-" * 50)
    print(f"Search cost: ${results['metadata']['cost']}")

Brave example (request body)

POST /api/web
{
  "query": "latest EU AI Act amendments",
  "provider": "brave",
  "depth": "standard",
  "outputType": "searchResults",
  "count": 10,
  "offset": 0,
  "safesearch": "moderate",
  "searchLang": "en",
  "uiLang": "en",
  "freshness": "2024-01-01to2024-02-01"
}

Advanced Examples

Deep Search with Date Filtering

def deep_search_with_dates(query, from_date, to_date):
    data = {
        "query": query,
        "depth": "deep",
        "fromDate": from_date,
        "toDate": to_date
    }
    
    response = requests.post(url, headers=headers, json=data)
    return response.json()

# Search for recent research
results = deep_search_with_dates(
    "quantum computing breakthroughs",
    "2025-01-01",
    "2025-07-01"
)

Structured Output for Data Extraction

def extract_structured_data(query, schema):
    data = {
        "query": query,
        "outputType": "structured",
        "structuredOutputSchema": json.dumps(schema)
    }
    
    response = requests.post(url, headers=headers, json=data)
    return response.json()

# Define schema for extracting programming language data
schema = {
    "type": "object",
    "properties": {
        "languages": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "rank": {"type": "number"},
                    "name": {"type": "string"},
                    "popularityScore": {"type": "string"},
                    "primaryUseCase": {"type": "string"}
                }
            }
        }
    }
}

# Extract structured data
results = extract_structured_data(
    "top 5 programming languages 2025",
    schema
)
def search_specific_domains(query, domains, exclude=False):
    data = {
        "query": query,
        "outputType": "sourcedAnswer"
    }
    
    if exclude:
        data["excludeDomains"] = domains
    else:
        data["includeDomains"] = domains
    
    response = requests.post(url, headers=headers, json=data)
    return response.json()

# Search only trusted news sources
news_results = search_specific_domains(
    "latest tech acquisitions",
    ["reuters.com", "bloomberg.com", "techcrunch.com"],
    exclude=False
)

# Exclude certain domains
filtered_results = search_specific_domains(
    "python tutorials",
    ["w3schools.com", "geeksforgeeks.org"],
    exclude=True
)

Error Handling

{
  "error": "Query parameter is required and must be a string"
}

Rate Limiting

The API is rate-limited to 60 requests per minute per IP address for /api/web. Internal or authenticated requests may have different limits. If you exceed this limit, you’ll receive a 429 status code.

Best Practices

  1. Use Standard Search for General Queries: Standard search is usually cheaper and sufficient for most use cases.
  2. Use Deep Search for Research: Deep search provides more comprehensive results and is ideal for research tasks or when you need extensive information.
  3. Leverage Domain Filtering: Use includeDomains to search specific trusted sources or excludeDomains to filter out unwanted sources.
  4. Date Filtering for Current Events: Use fromDate and toDate to get the most recent information on rapidly evolving topics.
  5. Structured Output for Data Extraction: Use structured output when you need to extract specific data points from search results in a predictable format.
  6. Handle Errors Gracefully: Always implement error handling for rate limits, insufficient balance, and network errors.
  7. Cache Results: Consider caching search results for identical queries to reduce costs and improve performance.

Output Type Selection Guide

  • searchResults: Best for general searches where you want to see multiple sources and snippets. Ideal for research and exploration.
  • sourcedAnswer: Best when you want a comprehensive answer synthesized from multiple sources. Great for factual questions and summaries.
  • structured: Best when you need to extract specific data points in a predictable format. Perfect for data collection and automation.

Pricing

ProviderStandardDeepNotes
Linkup$0.006$0.06Default provider
Tavily$0.008$0.016Good value, free tier available
Exa$0.005 base+ $0.001/pageFor contents retrieval
Kagi Web/News$0.002N/ACheapest for enrichment
Kagi Search$0.025N/AFull search mode
Perplexity$0.005N/AFlat rate
Valyu~$0.0015/resultVariableDynamic pricing
Brave$0.009$0.009Flat rate
OpenAI Native$0.01 + tokensN/APer-call fee + model token costs
A minimum balance of $1.00 is required to use the web search API. OpenAI native applies to GPT-5/o-series chat completions only and is not used by /api/web.

Bring your own key (BYOK)

BYOK is supported for Tavily, Exa, Kagi, Perplexity, and Valyu. Linkup and Brave always use NanoGPT’s key and are not BYOK on /api/web. When you supply your own provider key, NanoGPT does not add a platform charge for web search. Configure keys in team settings or pass them via headers.

X-402 payment protocol (optional)

Web search supports anonymous payment via the X-402 protocol. Accepted payment rails include Nano mainnet and Base USDC, using X-PAYMENT header schemes.