OpenSEO es un conjunto de herramientas de SEO de código abierto que necesita una fuente de datos SERP. La mayoría de los usuarios conectan proveedores costosos como DataForSEO ($50 mínimo) o SerpAPI ($25/mes). Este tutorial conecta a Scavio como fuente de datos a $0,005/consulta sin gasto mínimo. Obtiene el mismo seguimiento de clasificación, análisis de palabras clave y datos de funciones SERP a una fracción del costo.
Requisitos previos
- Python 3.8+
- solicita biblioteca
- Una clave API de Scavio de scavio.dev
- OpenSEO instalado o cualquier panel de SEO
Guia paso a paso
Paso 1: Construya el adaptador de datos Scavio para OpenSEO
Cree un adaptador que traduzca las respuestas de la API de Scavio al formato que espera OpenSEO.
import os, requests, json
from datetime import datetime
API_KEY = os.environ['SCAVIO_API_KEY']
SH = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
def scavio_serp(keyword, country='us'):
"""Fetch SERP data in OpenSEO-compatible format."""
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=SH, json={'query': keyword, 'country_code': country}, timeout=10).json()
organic = []
for i, r in enumerate(data.get('organic_results', [])):
organic.append({
'position': i + 1,
'title': r.get('title', ''),
'url': r.get('link', ''),
'domain': r.get('displayed_link', '').split('/')[0] if r.get('displayed_link') else '',
'snippet': r.get('snippet', ''),
})
paa = [q.get('question', '') for q in data.get('people_also_ask', [])]
featured = data.get('featured_snippet', {})
return {
'keyword': keyword,
'country': country,
'timestamp': datetime.now().isoformat(),
'organic_results': organic,
'people_also_ask': paa,
'has_featured_snippet': bool(featured),
'featured_snippet_domain': featured.get('displayed_link', ''),
'total_results': len(organic),
}
# Test
result = scavio_serp('best search api 2026')
print(f'Keyword: {result["keyword"]}')
print(f'Results: {result["total_results"]}')
print(f'PAA questions: {len(result["people_also_ask"])}')
for r in result['organic_results'][:3]:
print(f' #{r["position"]} {r["domain"]:25} {r["title"][:40]}')Paso 2: Seguimiento por lotes de palabras clave para OpenSEO
Realice un seguimiento de varias palabras clave y genere datos en el formato que consumen los paneles de OpenSEO.
def batch_track(keywords, domain, country='us'):
"""Track ranking positions for a domain across multiple keywords."""
results = []
for kw in keywords:
serp = scavio_serp(kw, country)
position = None
for r in serp['organic_results']:
if domain.lower() in r['url'].lower():
position = r['position']
break
results.append({
'keyword': kw,
'position': position,
'in_featured': serp['has_featured_snippet'] and domain in serp.get('featured_snippet_domain', ''),
'total_results': serp['total_results'],
'timestamp': serp['timestamp'],
})
status = f'#{position}' if position else 'not found'
print(f' {kw[:40]:40} | {status:10}')
ranked = sum(1 for r in results if r['position'])
avg_pos = sum(r['position'] for r in results if r['position']) / ranked if ranked else 0
print(f'\nSummary: {ranked}/{len(keywords)} ranked | Avg position: {avg_pos:.1f}')
print(f'Cost: ${len(keywords) * 0.005:.3f}')
return results
keywords = ['search api python', 'serp api pricing', 'mcp search tool', 'web search api free']
tracking = batch_track(keywords, 'scavio.dev')Paso 3: Exportar datos para importar OpenSEO
Guarde los datos de seguimiento en formatos CSV y JSON que OpenSEO pueda ingerir.
import csv
def export_for_openseo(results, domain):
# JSON export
json_file = f'openseo_tracking_{datetime.now().strftime("%Y%m%d")}.json'
with open(json_file, 'w') as f:
json.dump({'domain': domain, 'date': datetime.now().strftime('%Y-%m-%d'),
'keywords': results}, f, indent=2)
print(f' JSON: {json_file}')
# CSV export
csv_file = f'openseo_tracking_{datetime.now().strftime("%Y%m%d")}.csv'
with open(csv_file, 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['keyword', 'position', 'in_featured', 'timestamp'])
writer.writeheader()
for r in results:
writer.writerow({k: r[k] for k in ['keyword', 'position', 'in_featured', 'timestamp']})
print(f' CSV: {csv_file}')
print(f'\n Import into OpenSEO:')
print(f' 1. Go to OpenSEO > Data Sources > Import')
print(f' 2. Upload {json_file} or {csv_file}')
print(f' 3. Map fields: keyword, position, timestamp')
print(f'\n DataForSEO: $50 minimum, $0.002/query')
print(f' SerpAPI: $25/mo for 1K queries')
print(f' Scavio: No minimum, $0.005/query, 250 free/mo')
export_for_openseo(tracking, 'scavio.dev')Ejemplo en Python
import os, requests
SH = {'x-api-key': os.environ['SCAVIO_API_KEY'], 'Content-Type': 'application/json'}
def track_keyword(keyword, domain):
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=SH, json={'query': keyword, 'country_code': 'us'}, timeout=10).json()
pos = next((i+1 for i, r in enumerate(data.get('organic_results', [])) if domain in r.get('link', '')), None)
print(f'{keyword[:35]:35} | Position: {pos or "not found"}')
track_keyword('search api python', 'scavio.dev')Ejemplo en JavaScript
const SH = { 'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json' };
const data = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: SH,
body: JSON.stringify({ query: 'search api python', country_code: 'us' })
}).then(r => r.json());
const pos = (data.organic_results || []).findIndex(r => r.link?.includes('scavio.dev'));
console.log(`Position: ${pos >= 0 ? pos + 1 : 'not found'}`);Salida esperada
Keyword: best search api 2026
Results: 10
PAA questions: 4
#1 scavio.dev Best Search API for AI Agents - Scavio
#2 tavily.com Tavily Search API - AI-Optimized Search
#3 serpapi.com SerpAPI - Google Search API
search api python | #3
serp api pricing | #5
mcp search tool | #2
web search api free | #4
Summary: 4/4 ranked | Avg position: 3.5
Cost: $0.020
JSON: openseo_tracking_20260521.json
CSV: openseo_tracking_20260521.csv