Un buscador de brechas de palabras clave de SEO busca una lista de palabras clave objetivo, encuentra cuáles son las que los competidores clasifican entre las 10 primeras mientras que su dominio no aparece y genera las brechas como oportunidades de contenido procesables.
Requisitos previos
- Python 3.9+
- Clave API de Scavio
Guia paso a paso
Paso 1: Defina su dominio y sus competidores
Configure los dominios que desea comparar.
YOUR_DOMAIN = "yoursite.com"
COMPETITOR_DOMAINS = ["competitor1.com", "competitor2.com", "competitor3.com"]
KEYWORDS = [
"project management software",
"task tracker for teams",
"agile board online",
"kanban tool free",
"sprint planning tool"
]Paso 2: Busque cada palabra clave y extraiga posiciones
Para cada palabra clave, verifique si su dominio y sus competidores aparecen entre los 20 primeros resultados.
import requests
API_KEY = "your-scavio-api-key"
def get_positions(keyword: str, domains: list) -> dict:
r = requests.post(
"https://api.scavio.dev/api/v1/search",
json={"query": keyword, "num_results": 20},
headers={"x-api-key": API_KEY},
timeout=15
)
r.raise_for_status()
results = r.json().get("organic_results", [])
positions = {}
for domain in domains:
pos = next((i + 1 for i, res in enumerate(results) if domain in res.get("link","")), None)
positions[domain] = pos
return positionsPaso 3: Identificar lagunas de palabras clave
Una brecha es una palabra clave en la que al menos un competidor se ubica entre los 10 primeros, pero su dominio no.
def find_gaps(keywords: list, your_domain: str, competitor_domains: list) -> list:
all_domains = [your_domain] + competitor_domains
gaps = []
for kw in keywords:
positions = get_positions(kw, all_domains)
your_pos = positions.get(your_domain)
competitor_positions = {d: positions.get(d) for d in competitor_domains}
top10_competitors = [d for d, p in competitor_positions.items() if p and p <= 10]
if top10_competitors and (not your_pos or your_pos > 10):
gaps.append({
"keyword": kw,
"your_position": your_pos or "not ranking",
"competitors_ranking": {d: competitor_positions[d] for d in top10_competitors}
})
return gaps
gaps = find_gaps(KEYWORDS, YOUR_DOMAIN, COMPETITOR_DOMAINS)
for g in gaps:
print(f"GAP: {g['keyword']} | You: {g['your_position']} | {g['competitors_ranking']}")Ejemplo en Python
import requests
from datetime import date
API_KEY = "your-scavio-api-key"
YOUR_DOMAIN = "yoursite.com"
COMPETITORS = ["asana.com", "monday.com", "clickup.com"]
KEYWORDS = [
"project management software", "task tracker for teams",
"agile board online", "kanban tool free",
"sprint planning tool", "team task management"
]
def get_positions(keyword, domains):
r = requests.post("https://api.scavio.dev/api/v1/search",
json={"query": keyword, "num_results": 20},
headers={"x-api-key": API_KEY}, timeout=15)
r.raise_for_status()
results = r.json().get("organic_results", [])
return {d: next((i+1 for i, res in enumerate(results) if d in res.get("link","")), None)
for d in domains}
def find_gaps(keywords, your_domain, competitors):
all_domains = [your_domain] + competitors
gaps, covered = [], []
for kw in keywords:
pos = get_positions(kw, all_domains)
your_pos = pos[your_domain]
comp_top10 = {d: pos[d] for d in competitors if pos.get(d) and pos[d] <= 10}
if comp_top10 and (not your_pos or your_pos > 10):
gaps.append({"keyword": kw, "your_position": your_pos or "NR",
"gap_competitors": comp_top10})
elif your_pos and your_pos <= 10:
covered.append({"keyword": kw, "position": your_pos})
return {"gaps": gaps, "covered": covered}
if __name__ == "__main__":
result = find_gaps(KEYWORDS, YOUR_DOMAIN, COMPETITORS)
print(f"Keyword Gap Analysis — {YOUR_DOMAIN} — {date.today()}")
print(f"\nGAPS ({len(result['gaps'])} keywords — content opportunities):")
for g in result["gaps"]:
comp_str = ", ".join(f"{d}@{p}" for d, p in g["gap_competitors"].items())
print(f" {g['keyword']:<35} | You: {str(g['your_position']):<12} | {comp_str}")
print(f"\nCOVERED ({len(result['covered'])} keywords — protect these):")
for c in result["covered"]:
print(f" {c['keyword']:<35} | Position {c['position']}")Ejemplo en JavaScript
const API_KEY = 'your-scavio-api-key';
const YOUR_DOMAIN = 'yoursite.com';
const COMPETITORS = ['asana.com', 'monday.com'];
const KEYWORDS = ['project management software', 'task tracker for teams', 'kanban tool free'];
async function getPositions(keyword, domains) {
const res = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'x-api-key': API_KEY },
body: JSON.stringify({ query: keyword, num_results: 20 })
});
const data = await res.json();
const results = data.organic_results ?? [];
return Object.fromEntries(domains.map(d => [d, (results.findIndex(r => r.link?.includes(d)) + 1) || null]));
}
for (const kw of KEYWORDS) {
const positions = await getPositions(kw, [YOUR_DOMAIN, ...COMPETITORS]);
const yourPos = positions[YOUR_DOMAIN];
const compTop10 = COMPETITORS.filter(d => positions[d] && positions[d] <= 10);
if (compTop10.length && (!yourPos || yourPos > 10)) {
console.log(`GAP: ${kw} | You: ${yourPos ?? 'NR'} | Competitors: ${compTop10.join(', ')}`);
}
}Salida esperada
Keyword Gap Analysis - yoursite.com - 2026-05-22
GAPS (4 keywords - content opportunities):
project management software | You: NR | asana.com@2, monday.com@5
agile board online | You: NR | clickup.com@3
kanban tool free | You: 14 | asana.com@1, monday.com@7
sprint planning tool | You: NR | clickup.com@4, asana.com@8
COVERED (2 keywords - protect these):
task tracker for teams | Position 6
team task management | Position 9