Web Search

Search the web using the Kagi Search API via curl.

Process

  1. Set API key - Ensure KAGI_API_KEY environment variable is set
  2. Prepare query - URL encode search terms for special characters
  3. Make API request - Use curl with proper authorization header
  4. Filter results - Extract web results (t == 0) from response
  5. Format output - Use jq to parse and format the JSON response
  6. Report with links - When replying to users, always include direct source URLs

Examples

# Set API key first
export KAGI_API_KEY="your-api-key-here"

```bash
# Simple search
curl -s "https://kagi.com/api/v0/search?q=rust+programming&limit=10" \
  -H "Authorization: Bot $KAGI_API_KEY" \
  | jq .

# Search with URL encoding
query="how to install nix"
encoded=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$query'))")
curl -s "https://kagi.com/api/v0/search?q=$encoded&limit=5" \
  -H "Authorization: Bot $KAGI_API_KEY" \
  | jq '.data[] | select(.t == 0) | {title, url, snippet}'

Extract Search Results

# Get titles and URLs only
curl -s "https://kagi.com/api/v0/search?q=haskell+tutorials&limit=5" \
  -H "Authorization: Bot $KAGI_API_KEY" \
  | jq -r '.data[] | select(.t == 0) | "[\(.title)](\(.url))"'

# Get formatted results with snippets
curl -s "https://kagi.com/api/v0/search?q=nix+flakes&limit=5" \
  -H "Authorization: Bot $KAGI_API_KEY" \
  | jq -r '.data[] | select(.t == 0) | "\n\(.title)\n\(.url)\n\(.snippet // "No snippet")\n"'

Using Python

For more complex parsing:

cat > /tmp/kagi_search.py << 'EOF'
import os
import sys
import json
import urllib.parse
import urllib.request

def search_kagi(query, limit=10):
    api_key = os.environ.get('KAGI_API_KEY')
    if not api_key:
        print("Error: KAGI_API_KEY not set", file=sys.stderr)
        sys.exit(1)
    
    encoded_query = urllib.parse.quote(query)
    url = f"https://kagi.com/api/v0/search?q={encoded_query}&limit={limit}"
    
    req = urllib.request.Request(url)
    req.add_header('Authorization', f'Bot {api_key}')
    
    try:
        with urllib.request.urlopen(req) as response:
            data = json.loads(response.read())
            return data.get('data', [])
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == '__main__':
    query = sys.argv[1] if len(sys.argv) > 1 else "test"
    limit = int(sys.argv[2]) if len(sys.argv) > 2 else 10
    
    results = search_kagi(query, limit)
    
    # Filter to regular results (t == 0)
    web_results = [r for r in results if r.get('t') == 0]
    
    for i, result in enumerate(web_results, 1):
        print(f"{i}. {result.get('title', 'No title')}")
        print(f"   {result.get('url', 'No URL')}")
        snippet = result.get('snippet', '')
        if snippet:
            print(f"   {snippet[:200]}")
        print()
EOF

python3 /tmp/kagi_search.py "haskell monads"

Response Format

The Kagi API returns JSON with this structure:

{
  "data": [
    {
      "t": 0,           // 0 = web result, other types exist
      "url": "https://example.com",
      "title": "Page Title",
      "snippet": "Description text...",
      "published": "2024-01-01"  // Optional
    }
  ]
}

Tips

  1. Always filter by t == 0 to get regular web results
  2. Limit results - default is 10, max is 20
  3. URL encode queries - especially for special characters
  4. Check API key - verify $KAGI_API_KEY is set before calling
  5. Handle errors - API may return error JSON with non-200 status
  6. Always cite URLs in answers - never summarize web findings without links

Common Patterns

# Quick search with formatted output
kagi_search() {
  local query="$1"
  local limit="${2:-5}"
  local encoded=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$query'))")
  curl -s "https://kagi.com/api/v0/search?q=$encoded&limit=$limit" \
    -H "Authorization: Bot $KAGI_API_KEY" \
    | jq -r '.data[] | select(.t == 0) | "\(.title)\n\(.url)\n"'
}

kagi_search "rust web frameworks"

Error Handling

# Check for errors in response
response=$(curl -s "https://kagi.com/api/v0/search?q=test&limit=5" \
  -H "Authorization: Bot $KAGI_API_KEY")

if echo "$response" | jq -e '.error' > /dev/null 2>&1; then
  echo "API Error:" $(echo "$response" | jq -r '.error')
  exit 1
fi