SearchCans

API Documentation

Complete guide to SearchCans SERP API and Reader API

API Overview - Dual Engine Platform

SearchCans provides two powerful APIs for AI applications:

Quick Start

Get started with SearchCans API in minutes:

  1. Sign up for a free account
  2. Get your API key from the Dashboard
  3. 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.

Python - Batch Search Tool
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()
              
Usage:
  1. Create keywords.txt with one keyword per line
  2. Replace YOUR_API_KEY with your actual API key
  3. Run: python serp_search.py
  4. Results saved as individual JSON files + summary JSONL

Features: Automatic retry on failure, progress tracking, batch result export.

Related Guides & 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:

LLM-ready Markdown output - Perfect for RAG and AI agents
Lossless conversion - Preserves all semantic information
Structured data extraction - Title, author, date, images, links
10x cheaper than alternatives - Jina Reader, Firecrawl

→ 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

Python
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:

📄 Markdown (.md)

Perfect for LLM training, RAG pipelines, and documentation

🌐 HTML (.html)

Full page source for archiving and analysis

📦 JSON (.json)

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

Error: "Timeout" or "Request timeout"
  • • Increase d parameter to 25000-30000ms
  • • Check if target website is accessible
  • • Set your code's timeout higher than d parameter
Error: "Data parsing failed"
  • • Check if response.data is a string, use JSON.parse()
  • • Validate the response structure before accessing fields
Issue: "Missing content or empty markdown"
  • • Set b: true to enable browser rendering
  • • Increase w to 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

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 code field before processing data
  • 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:

Related Resources