API Documentation
Complete guide to SearchCans SERP API and Reader API
API Overview - Dual Engine Platform
SearchCans provides two powerful APIs for AI applications:
SERP API
Get real-time SERP data from Google and via our Bing Search API. Perfect for SEO tools, market research, and AI applications that need to search the web.
View SERP API Docs →Reader API
Our URL to Markdown API turns any web page into clean structured markdown. Ideal for RAG pipelines and processing web content.
View Reader API Docs →Quick Start
Get started with SearchCans API in minutes:
- Sign up for a free account
- Get your API key from the Dashboard
- Make your first API call
Authentication
SearchCans API uses Bearer Token authentication. Include your API key in the request header:
Authorization: Bearer YOUR_API_KEY
SERP API - Google & Bing Search API
Endpoint
POST https://www.searchcans.com/api/search
GET https://www.searchcans.com/api/search
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| s | string | Yes | Search keyword |
| t | string | Yes | Search engine type: google or bing |
| d | number | No | Maximum API wait time (ms), default 10000. Recommended: 10000-15000ms for stable results |
| p | number | No | Page number, default 1 |
Request Examples
curl -X POST https://www.searchcans.com/api/search \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"s": "artificial intelligence",
"t": "google",
"p": 1,
"d": 10000
}'Response Example
{
"code": 0,
"msg": "Success",
"data": [
{
"title": "Search result title",
"url": "https://example.com",
"content": "Search result summary content..."
}
]
}
Production-Ready Code Example
Batch keyword search tool with automatic retry and result saving.
import requests
import json
import time
import os
from datetime import datetime
# Configuration
API_KEY = "YOUR_API_KEY"
API_URL = "https://www.searchcans.com/api/search"
KEYWORDS_FILE = "keywords.txt" # One keyword per line
OUTPUT_DIR = "serp_results"
SEARCH_ENGINE = "google" # or "bing"
MAX_RETRIES = 3
def load_keywords(filepath):
"""Load keywords from file"""
if not os.path.exists(filepath):
print(f" Error: {filepath} not found")
return []
keywords = []
with open(filepath, 'r', encoding='utf-8') as f:
for line in f:
keyword = line.strip()
if keyword and not keyword.startswith('#'):
keywords.append(keyword)
return keywords
def search_keyword(keyword, page=1):
"""Search single keyword with SERP API"""
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
payload = {
"s": keyword,
"t": SEARCH_ENGINE,
"d": 10000, # 10s timeout
"p": page
}
try:
response = requests.post(API_URL, headers=headers, json=payload, timeout=15)
result = response.json()
if result.get("code") == 0:
print(f" Success: {len(result.get('data', []))} results")
return result
else:
print(f" Failed: {result.get('msg')}")
return None
except Exception as e:
print(f" Error: {e}")
return None
def search_with_retry(keyword):
"""Search with automatic retry"""
for attempt in range(MAX_RETRIES):
if attempt > 0:
print(f" Retry {attempt}/{MAX_RETRIES-1}...")
time.sleep(2)
result = search_keyword(keyword)
if result:
return result
print(f" Failed after {MAX_RETRIES} attempts")
return None
def save_result(keyword, result, output_dir):
"""Save search result"""
# Create safe filename
safe_name = "".join(c if c.isalnum() or c in (' ', '-', '_') else '_' for c in keyword)
safe_name = safe_name[:50]
# Save as individual JSON
json_file = os.path.join(output_dir, f"{safe_name}.json")
with open(json_file, 'w', encoding='utf-8') as f:
json.dump(result, f, ensure_ascii=False, indent=2)
# Also save to summary JSONL
jsonl_file = os.path.join(output_dir, "all_results.jsonl")
with open(jsonl_file, 'a', encoding='utf-8') as f:
record = {
"keyword": keyword,
"timestamp": datetime.now().isoformat(),
"result": result
}
f.write(json.dumps(record, ensure_ascii=False) + "
")
print(f" Saved: {safe_name}.json")
def main():
"""Main execution"""
print(" SearchCans SERP API Batch Search Tool")
print("=" * 60)
# Load keywords
keywords = load_keywords(KEYWORDS_FILE)
if not keywords:
return
total = len(keywords)
print(f" Loaded {total} keywords
")
# Create output directory
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
output_dir = f"{OUTPUT_DIR}_{timestamp}"
os.makedirs(output_dir, exist_ok=True)
print(f" Output: {output_dir}/
")
# Process each keyword
completed = 0
for index, keyword in enumerate(keywords, 1):
print(f"[{index}/{total}] Keyword: {keyword}")
result = search_with_retry(keyword)
if result:
save_result(keyword, result, output_dir)
# Extract and display URLs
urls = [item.get("url", "") for item in result.get("data", [])]
if urls:
print(f" {len(urls)} URLs found")
for i, url in enumerate(urls[:3], 1):
print(f" {i}. {url[:70]}...")
completed += 1
# Rate limiting
if index < total:
time.sleep(1)
# Summary
print("
" + "=" * 60)
print(f" Summary: {completed}/{total} successful")
print(f" Results saved to: {output_dir}/")
if __name__ == "__main__":
main()
- Create
keywords.txtwith one keyword per line - Replace
YOUR_API_KEYwith your actual API key - Run:
python serp_search.py - Results saved as individual JSON files + summary JSONL
Features: Automatic retry on failure, progress tracking, batch result export.
Related Guides & Tutorials
Tutorials:
Also Available:
- • Reader API →
- Turn any URL into clean, LLM-ready Markdown. Perfect for RAG pipelines and AI training data.
Reader API - URL to Markdown Conversion
Why Reader API? The LLM-Ready Solution
Our URL to Markdown solution provides clean, structured, LLM-ready Markdown - the universal format for AI applications:
→ Why Markdown is the universal language for AI applications
Endpoint
POST https://www.searchcans.com/api/url
GET https://www.searchcans.com/api/url
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| s | string | Yes | URL to extract content from |
| t | string | Yes | Type, fixed value: url |
| w | number | No | Wait time after opening URL (milliseconds), default 3000. Recommended: 3000-5000ms for JavaScript-heavy sites |
| d | number | No | Maximum wait time for API (milliseconds), default 20000. Recommended: 20000-30000ms for complex pages |
| b | boolean | No | Use browser rendering, default true. Set to true for JavaScript-heavy sites (SPAs, React, Vue apps) |
Request Examples
curl -X POST https://www.searchcans.com/api/url \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"s": "https://example.com",
"t": "url",
"w": 3000,
"d": 20000,
"b": true
}'Response Example
{
"code": 0,
"msg": "Success",
"data": {
"title": "Article Title",
"description": "Article description or meta description",
"markdown": "# Heading\n\nClean markdown content...",
"html": "<html>...</html>"
}
}
// Note: In some cases, 'data' may be a JSON string that needs parsing:
// const parsedData = JSON.parse(response.data);
💡 Parameter Usage Tips
- w (wait time): Increase to 3000-5000ms for JavaScript-heavy sites (SPAs, React, Vue apps). Default 3000ms is suitable for most modern websites.
- d (timeout): Set to 20000-30000ms for complex pages with slow loading. If you encounter timeout errors, increase this value.
- b (browser mode):
- •
true: Full JavaScript rendering, slower but complete (2-5s). Recommended for SPAs and dynamic content. - •
false: Fast static extraction, may miss JS-generated content (0.5-1s). Use for simple HTML pages.
- •
Production-Ready Example with Error Handling
import requests
import json
import time
def extract_content(url, retry=3):
"""
Extract content with optimal settings and error handling
"""
api_url = "https://www.searchcans.com/api/url"
headers = {
"Authorization": f"Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}
payload = {
"s": url,
"t": "url",
"w": 3000, # 3s wait for JS rendering
"d": 20000, # 20s max timeout
"b": True # Enable browser mode
}
for attempt in range(retry):
try:
# Set timeout slightly higher than 'd' parameter
response = requests.post(
api_url,
headers=headers,
json=payload,
timeout=25
)
result = response.json()
if result["code"] == 0:
# Parse the data (may be string or object)
data = result["data"]
if isinstance(data, str):
data = json.loads(data)
return {
"title": data.get("title", ""),
"markdown": data.get("markdown", ""),
"html": data.get("html", ""),
"description": data.get("description", "")
}
else:
print(f"API Error: {result.get('msg')}")
if attempt < retry - 1:
time.sleep(2) # Wait before retry
continue
return None
except requests.exceptions.Timeout:
print(f"Timeout on attempt {attempt + 1}/{retry}")
if attempt < retry - 1:
time.sleep(2)
continue
return None
except Exception as e:
print(f"Error: {str(e)}")
return None
return None
# Usage Example
if __name__ == "__main__":
url = "https://example.com/article"
content = extract_content(url)
if content:
print(f"✅ Title: {content['title']}")
print(f"📄 Content length: {len(content['markdown'])} characters")
# Save to file
with open("output.md", "w", encoding="utf-8") as f:
f.write(f"# {content['title']}\n\n")
f.write(content['markdown'])
print("✅ Saved to output.md")
else:
print("❌ Extraction failed")
💡 Complete Data Structure
The Reader API returns a rich data structure with multiple formats:
{
"title": "Article Title", // Page title
"description": "Meta description", // SEO description
"markdown": "# Clean content...", // LLM-ready Markdown
"html": "<html>...</html>" // Full HTML source
} Save in Multiple Formats:
Perfect for LLM training, RAG pipelines, and documentation
Full page source for archiving and analysis
Structured data with all metadata for databases
Pro Tip: Save all three formats for maximum flexibility. Markdown for AI, HTML for backup, JSON for metadata.
⚠️ Common Errors & Solutions
- • Increase
dparameter to 25000-30000ms - • Check if target website is accessible
- • Set your code's timeout higher than
dparameter
- • Check if
response.datais a string, useJSON.parse() - • Validate the response structure before accessing fields
- • Set
b: trueto enable browser rendering - • Increase
wto 5000ms for heavy JavaScript sites - • Note: Some websites have advanced anti-scraping protection. For sites with high-level anti-bot measures, we cannot guarantee 100% success rate in content extraction.
Related Guides & Tutorials
Learn More:
Also Available:
- • SERP API (Search API) →
- Get real-time search results from Google and Bing. Perfect for SEO tools and market research.
Response Codes & Error Handling
All API responses include a code field in the JSON body to indicate the request status. Understanding these codes helps you handle errors effectively.
| Code | Type | Description | Solution |
|---|---|---|---|
| 200 | Success | Request processed successfully | No action needed |
| -1001 | Response Timeout | The API request exceeded the wait time | Increase the d parameter (e.g., 15000-20000ms) or check target website accessibility |
| 443 | Connection Error | SSL/Network port connection issues | Verify network connectivity, check firewall settings, ensure SSL certificates are valid |
| 10054 | Connection Reset | Remote host forcibly closed the connection | Retry the request, check if target website is blocking requests, consider adding delay between requests |
| 401 | Unauthorized | Invalid or missing API key | Check your API key in the Authorization header, get a new key from Dashboard |
| 403 | Forbidden | Insufficient permissions or quota exceeded | Check your account quota on Dashboard, upgrade plan if needed |
| 429 | Rate Limit Exceeded | Too many requests in a short time | Implement request throttling, add delays between requests, or upgrade to a higher tier plan |
| 500 | Internal Server Error | Server encountered an unexpected error | Retry after a few seconds, if persists contact Technical Support |
💡 Best Practices for Error Handling
- Always check the
codefield before processingdata - Implement retry logic with exponential backoff for timeout errors (-1001)
- Log error codes and messages for debugging
- Set appropriate timeout values based on your use case (SERP API: 10-15s, Reader API: 15-30s)
Technical Support
If you encounter any issues, please contact us:
- Visit our API Playground for online testing
- Check the Pricing page for more package information
- Read our FAQ for common questions
- Submit a technical support request through the Dashboard