Web Search
Search the web using the Kagi Search API via curl.
Process
- Set API key - Ensure
KAGI_API_KEYenvironment variable is set - Prepare query - URL encode search terms for special characters
- Make API request - Use curl with proper authorization header
- Filter results - Extract web results (t == 0) from response
- Format output - Use jq to parse and format the JSON response
- 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
- Always filter by
t == 0to get regular web results - Limit results - default is 10, max is 20
- URL encode queries - especially for special characters
- Check API key - verify
$KAGI_API_KEYis set before calling - Handle errors - API may return error JSON with non-200 status
- 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