SEO tools
Google organic search: keywords, rankings, results pages, domains, backlinks and site health.
Research Google organic search: keywords, rankings, results pages, domains, backlinks and site health. The data comes from DataForSEO, except seo_get_page, which fetches the page itself and is free, and the Ahrefs DR in seo_get_domain_ratings, which comes free from Ahrefs.
A few terms the results use:
- Volume is monthly searches.
- KD is keyword difficulty, from 0 to 100.
- domain_rank is DataForSEO's authority score from its backlink index, from 0 to 1000. It is the same kind of number as Ahrefs DR or Moz DA, but on a different scale.
- ahrefs_dr is Ahrefs Domain Rating itself, from 0 to 100. It always rates the registered domain, so
www.github.comandgist.github.comboth get the rating ofgithub.com, whiledomain_rankrates the host you give. Wherever you show it, show "Domain Rating by Ahrefs" with a link to ahrefs.com next to it. - A target is a domain or a URL. See targets.
Where to start depends on the question. Keyword research is one seo_search_keywords call, which already includes the metrics. To look at a domain, start with seo_get_domain_overview, then look at its backlinks or the keywords it ranks for. For site health, seo_get_page checks one URL, and seo_run_technical_crawl checks a whole site as an async task. If you already run Screaming Frog on your desktop, its own server is covered in the Screaming Frog MCP setup guide. For your own site's clicks, rankings and indexing in Google and Bing, use the console tools, and for what visitors did next, the Analytics tools. Both cost 0 credits.
To connect these tools to your agent, see the SEO MCP page.
| Tool | What it does | Cost |
|---|---|---|
seo_search_keywords | Get keyword ideas | From 5 credits |
seo_get_keyword_metrics | Check keyword metrics | From 5 credits |
seo_get_serp | Get search results for a query | From 1 credit |
seo_get_position | Get a site's position for a keyword | From 6 credits |
seo_get_domain_overview | Get a domain overview | From 15 credits |
seo_get_ranked_keywords | Get a domain's ranked keywords | From 5 credits |
seo_get_serp_competitors | Find search competitors | From 5 credits |
seo_get_keyword_gap | Find keyword gaps | From 5 credits |
seo_get_backlink_summary | Get a backlink summary | From 10 credits |
seo_get_backlinks | Get backlinks | From 10 credits |
seo_get_referring_domains | Get referring domains | From 10 credits |
seo_get_domain_ratings | Get domain ratings in bulk | From 7 credits |
seo_get_traffic_estimates | Get traffic estimates in bulk | From 50 credits |
seo_get_page | Get an on-page snapshot | Free |
seo_run_technical_crawl | Run a technical audit | From 5 credits |
Get keyword ideas
seo_search_keywordsCandidate keywords around a seed, with volume, difficulty, intent, CPC and trend for each.
"find keywords for X", "what should I target around X", "keyword ideas for a page about X".
- Metrics on keywords the user already has, use
seo_get_keyword_metrics(this tool already returns those metrics, so do not call it afterwards). - Prompts people ask AI engines, use
aeo_search_prompts. - The top-10 page for one query, use
seo_get_serp.
A list. Each row has keyword, volume, kd (0 to 100), intent, cpc (USD), competition, bid_low, bid_high (Google Ads top-of-page bid range, USD), trend[12] (month, volume). volume, kd, cpc null = provider has no data; 0 = measured zero.
5 + 5 per 100 rows. Default 100 rows = 10 credits. Cached 7 days.
Parameters
| Parameter | Default and notes |
|---|---|
seed | Required. The seed keyword or topic. |
mode | Default suggestions. suggestions: keywords that contain the seed. related: keywords whose results page is like the seed's. ideas: keywords in the same category. |
location | Provider location name or code. Default United States. |
language | ISO 639-1 language code. Default en. |
limit | Max rows. Default 100, cap 1000. |
It also takes the common parameters cursor, max_credits and dry_run.
{
"seed": "crm for startups",
"mode": "suggestions",
"limit": 50
}Check keyword metrics
seo_get_keyword_metricsVolume, difficulty, intent, CPC and 12-month trend for keywords you already have, with AI-engine prompt volume on request.
The user supplies keywords, or you need numbers for a list from elsewhere. ai_volume true when the question is how often AI engines see the keyword.
- Discovering keywords, use
seo_search_keywords(it already includes these metrics, do not call this after it). - AI-engine prompts, use
aeo_search_prompts. - Checking rankings, use
seo_get_position.
A list. Each row has keyword, volume, kd, intent, cpc, competition, bid_low, bid_high (Google Ads top-of-page bid range, USD), trend[12], ai_volume, ai_trend[12]. One row per input keyword in the order given. volume/kd null = provider has no data; 0 = measured zero. With source google_ads, kd and intent are always null and keywords over 80 characters come back all null. ai_volume and ai_trend are null unless ai_volume is true.
5 + 5 per 100 keywords with source labs; 24 flat with source google_ads; ai_volume adds 4 + 4 per 100 keywords. Default 100 keywords = 10 credits. Cached 7 days.
Parameters
| Parameter | Default and notes |
|---|---|
keywords[] | Required. At most 1000. |
source | Default labs. One of labs, google_ads. google_ads is Keyword Planner's own volume, slower; no kd or intent. |
ai_volume | Default false. Also return AI-engine prompt volume. |
location | Provider location name or code. Default United States. |
language | ISO 639-1 language code. Default en. |
It also takes the common parameters max_credits and dry_run.
{
"keywords": [
"crm for startups",
"hubspot alternative"
],
"ai_volume": true
}Get search results for a query
seo_get_serpThe top organic results and SERP features Google shows for one query.
"what ranks for X", "who is on page one for X", "is there a featured snippet or AI overview for X".
- Where one site ranks for a keyword, use
seo_get_position(it scans the top 100 for you). - Keyword ideas, use
seo_search_keywords. - The businesses Google Maps ranks for a local search, use
maps_search_places.
One record with features[] (featured_snippet, people_also_ask, video, ai_overview and others), results[] (rank, organic_rank, type, url, domain, title, snippet, published_at, rating), related_searches[], ai_overview (text, references[]) or null, results_count, check_url. depth counts organic rows: the default returns 10 organic results whenever Google has them, with the features ranked among them on top. Each People Also Ask question and each forum thread is its own row at its block's rank; for a question, title is the question and snippet the answer, url null when Google's answer is an AI overview. domain is null on a row whose url is still a google.com/goto redirect. location localises the local pack, not the organic rows of a bare service search: put the town in the keyword ("dentist columbus ohio") for local organic results. Paid ads seldom come back, so the page says nothing about who bids on the query; a named rival's search ads are in ads_get_advertiser_ads with platform google.
1 credit per 10 results, +1 with ai_overview. Default top 10 = 1 credit. Cached 24 hours.
Parameters
| Parameter | Default and notes |
|---|---|
keyword | Required. |
location | Provider location name or code. Default United States. |
language | ISO 639-1 language code. Default en. |
device | Default desktop. One of desktop, mobile. |
depth | How many results to fetch. Default 10, max 100. |
ai_overview | Default false. Also return Google's AI overview and its cited sources. +1 credit. |
It also takes the common parameters max_credits and dry_run.
{
"keyword": "hubspot alternative",
"depth": 10,
"ai_overview": true
}Get a site's position for a keyword
seo_get_positionWhere one target ranks for one keyword, scanning the top 100 server-side.
"where does example.com rank for X", "did we make page one for X", a rank check for a handful of keywords.
- Every keyword a domain ranks for, use
seo_get_ranked_keywords. - The full page-one list, use
seo_get_serp. - Tracking over time:
monitoring_create_monitorwithgoogle_rankings.
One record with keyword, target, rank (absolute, null when not in the top 100), organic_rank, url, title, scanned_depth, above[] (rank, domain, url of the organic results just ahead, at most 10, nearest last). For a local business, location does not localise the organic rank of a bare service search ("dentist"); put the town in the keyword ("dentist columbus ohio"), or use maps_search_places for the Maps rank.
6 credits flat, also when the target is not in the top 100. NoData (free) only when the keyword has no organic results. Cached 24 hours.
Parameters
| Parameter | Default and notes |
|---|---|
keyword | Required. |
target | Required. Domain or URL. example.com covers all subdomains, www.example.com is that host only, a full URL is that page only. |
location | Provider location name or code. Default United States. |
language | ISO 639-1 language code. Default en. |
device | Default desktop. One of desktop, mobile. |
It also takes the common parameters max_credits and dry_run.
{
"keyword": "hubspot alternative",
"target": "example.com"
}Get a domain overview
seo_get_domain_overviewTraffic estimate, ranked keyword count, position spread, top pages and domain rank for one domain. The canonical source of domain rank.
"how strong is competitor.com", "how much traffic does X get", sizing a site before a deeper look.
- The keywords behind the traffic, use
seo_get_ranked_keywords. - Link counts, use
seo_get_backlink_summary(itsdomain_rankequals this one). - Many domains at once, use
seo_get_domain_ratingsfor domain rank orseo_get_traffic_estimatesfor traffic.
One record with domain_rank (0 to 1000 on DataForSEO, the same kind of number as Ahrefs DR or Moz DA but not the same scale), organic_traffic, organic_keywords, organic_traffic_cost (USD), positions (top_3, top_10, top_100), keyword_changes (new, up, down, lost since the provider's previous update), paid_traffic, paid_keywords, top_pages[] (url, organic_traffic, organic_keywords), history[] (12 months: month, organic_traffic, organic_keywords) only with history true. null = provider has no data. A traffic figure saved before 1 November 2026 may be on DataForSEO's older traffic model: take a new baseline rather than compare across that date. history[] may keep the older model, so compare its months with each other, not with organic_traffic.
15 credits; +56 with history. Cached 7 days.
Parameters
| Parameter | Default and notes |
|---|---|
target | Required. Domain or URL. example.com covers all subdomains, www.example.com is that host only, a full URL is that page only. |
location | Provider location name or code. Default United States. |
language | ISO 639-1 language code. Default en. |
history | Default false. Also return 12 months of organic traffic and keywords. |
It also takes the common parameters max_credits and dry_run.
{
"target": "competitor.com"
}Get a domain's ranked keywords
seo_get_ranked_keywordsKeywords a domain or one page ranks for in the top 100, with position, URL and metrics.
"what does competitor.com rank for", "which keywords send traffic to this page", building a list of a site's topics.
- Keywords a competitor has that you do not, use
seo_get_keyword_gap. - One keyword's position, use
seo_get_position. - New keyword ideas, use
seo_search_keywords.
A list. Each row has keyword, rank, type (organic, featured_snippet or local_pack; ads excluded), previous_rank (null = did not rank at the provider's previous update), is_new, url, volume, kd, cpc, intent, traffic (estimated monthly visits from this keyword), serp_features[] (SERP feature types on the keyword's page). A keyword can appear once per type. Sorted by traffic, highest first. rank counts every element on the page, ads and features included, so a keyword in the organic top 100 can read rank 104. null = provider has no data. A traffic figure saved before 1 November 2026 may be on DataForSEO's older traffic model: take a new baseline rather than compare across that date.
5 + 5 per 100 rows. Default 100 rows = 10 credits. Cached 7 days.
Parameters
| Parameter | Default and notes |
|---|---|
target | Required. Domain or URL. example.com covers all subdomains, www.example.com is that host only, a full URL is that page only. |
location | Provider location name or code. Default United States. |
language | ISO 639-1 language code. Default en. |
limit | Max rows. Default 100, cap 1000. |
It also takes the common parameters cursor, max_credits and dry_run.
{
"target": "competitor.com",
"limit": 200
}Find search competitors
seo_get_serp_competitorsDomains that share search results with a target, with how many keywords overlap. SERP competitors, not business competitors.
"who competes with example.com in search", "which sites show up for the same queries as X", choosing competitors for a keyword gap.
- The keywords themselves, use
seo_get_keyword_gap. - A single domain's strength, use
seo_get_domain_overview.
A list. Each row has domain, shared_keywords, avg_position, organic_traffic, organic_keywords, paid_traffic, paid_keywords. Sorted by shared keywords. The target itself is excluded. A traffic figure saved before 1 November 2026 may be on DataForSEO's older traffic model: take a new baseline rather than compare across that date.
5 + 5 per 100 rows. Default 100 rows = 10 credits. Cached 7 days.
Parameters
| Parameter | Default and notes |
|---|---|
target | Required. Domain or URL. example.com covers all subdomains, www.example.com is that host only, a full URL is that page only. |
location | Provider location name or code. Default United States. |
language | ISO 639-1 language code. Default en. |
limit | Max rows. Default 100, cap 1000. |
It also takes the common parameters cursor, max_credits and dry_run.
{
"target": "example.com",
"limit": 20
}Find keyword gaps
seo_get_keyword_gapKeywords one competitor ranks for in the top 100 that the target does not rank for at all.
"what does competitor.com rank for that we do not", "find gaps against X", content opportunities from a rival.
- Everything a domain ranks for, use
seo_get_ranked_keywords. - Finding who the competitors are, use
seo_get_serp_competitors. - Fresh ideas around a topic, use
seo_search_keywords.
A list. Each row has keyword, competitor, competitor_rank, competitor_url, volume, kd, cpc, intent. Sorted by volume.
5 + 5 per 100 rows. Default 100 rows = 10 credits. Cached 7 days.
Parameters
| Parameter | Default and notes |
|---|---|
target | Required. Domain or URL. example.com covers all subdomains, www.example.com is that host only, a full URL is that page only. |
competitor | Required. One competitor's domain. A URL is read as its host. |
location | Provider location name or code. Default United States. |
language | ISO 639-1 language code. Default en. |
limit | Max rows. Default 100, cap 1000. |
It also takes the common parameters cursor, max_credits and dry_run.
{
"target": "example.com",
"competitor": "competitor.com",
"limit": 100
}Get a backlink summary
seo_get_backlink_summaryLink totals for a domain or page: backlinks, referring domains, dofollow share, link types and domain rank.
"how many links does X have", "what is X's link profile like", a quick authority check alongside seo_get_domain_overview.
- The individual links or their anchor text, use
seo_get_backlinks. - The sites linking, use
seo_get_referring_domains. - Domain rank for many domains, use
seo_get_domain_ratings.
One record with domain_rank (equals seo_get_domain_overview's domain_rank), backlinks, referring_domains, referring_main_domains, referring_ips, dofollow_share (0 to 1), broken_backlinks (links to a page of the target that answers 4xx or 5xx), broken_pages (such pages), spam_score (backlinks' average, 0 to 100), target_spam_score, first_seen, and counts by link type, attribute, placement, platform, TLD and country (top 10). null = provider has no data.
10 credits flat. Cached 7 days.
Parameters
| Parameter | Default and notes |
|---|---|
target | Required. Domain or URL. example.com covers all subdomains, www.example.com is that host only, a full URL is that page only. |
include_subdomains | Default true. Count links to subdomains too. Ignored for a URL target. |
It also takes the common parameters max_credits and dry_run.
{
"target": "competitor.com"
}Get backlinks
seo_get_backlinksIndividual backlinks pointing at a domain or page, strongest referring domain first.
"show me the links to this page", "which pages link to competitor.com", finding link sources to replicate, "which links did we lose" (status lost).
- Totals only, use
seo_get_backlink_summary. - One row per linking site, use
seo_get_referring_domains. - Rating the linking sites, use
seo_get_domain_ratings.
A list. Each row has url_from, url_to, domain_from, dr_from, page_title, anchor, dofollow, rel[] (nofollow, sponsored, ugc and other rel values), type, spam_score (0 to 100), url_to_status (HTTP status of url_to), broken (url_to answers 4xx or 5xx), first_seen, last_seen (for a lost link, about when it went), lost (only with status lost or all). dr_from is the linking domain's own rank, 0 to 1000.
10 + 1.5 per 100 rows. Default 100 rows = 12 credits. Cached 7 days.
Parameters
| Parameter | Default and notes |
|---|---|
target | Required. Domain or URL. example.com covers all subdomains, www.example.com is that host only, a full URL is that page only. |
include_subdomains | Default true. Count links to subdomains too. Ignored for a URL target. |
status | Default live. live: links found at the last check. lost: links since removed. all: both. |
limit | Max rows. Default 100, cap 1000. |
It also takes the common parameters cursor, max_credits and dry_run.
{
"target": "https://competitor.com/blog/best-crm",
"limit": 50
}Get referring domains
seo_get_referring_domainsDomains linking to a target, one row per domain, with the rank each passes, link counts and spam score.
"who links to competitor.com", "build a list of sites to pitch for links", link prospecting from a rival's profile, "which sites stopped linking to us" (status lost).
- Every individual link, use
seo_get_backlinks. - Totals, use
seo_get_backlink_summary. - Rating your own list of domains, use
seo_get_domain_ratings.
A list. Each row has domain, rank_passed (0 to 1000: the rank this domain's links pass to the target, not the domain's own rank, which seo_get_domain_ratings gives), backlinks, referring_pages, dofollow_backlinks, broken_backlinks (its links to a page of the target that answers 4xx or 5xx), spam_score, first_seen, lost (a link from it was lost; only with status lost or all). Sorted by rank_passed, so the strongest linking sites are not necessarily first: rate the domains before filtering by authority.
10 + 1.5 per 100 rows. Default 100 rows = 12 credits. Cached 7 days.
Parameters
| Parameter | Default and notes |
|---|---|
target | Required. Domain or URL. example.com covers all subdomains, www.example.com is that host only, a full URL is that page only. |
include_subdomains | Default true. Count links to subdomains too. Ignored for a URL target. |
status | Default live. live: links found at the last check. lost: links since removed. all: both. |
limit | Max rows. Default 100, cap 1000. |
It also takes the common parameters cursor, max_credits and dry_run.
{
"target": "competitor.com",
"limit": 200
}Get domain ratings in bulk
seo_get_domain_ratingsDomain rank and Ahrefs DR only, for up to 1,000 domains in one call. The cheap way to rate a list.
"rate these domains", "which of these sites are worth a link", filtering a prospect list by authority.
- Traffic numbers, use
seo_get_traffic_estimates(10x the cost). - A full profile of one domain, use
seo_get_domain_overvieworseo_get_backlink_summary.
A list. Each row has domain, domain_rank (0 to 1000 on DataForSEO, for the host as given; 0 for a domain the index does not know), ahrefs_dr (Ahrefs Domain Rating, 0 to 100, always for the registered domain, so www.github.com and gist.github.com both get github.com's; 0 for a domain Ahrefs does not know, null when it did not answer). One row per distinct domain, in the order first given: duplicates and case variants are merged, and a full URL is rated by its host. ahrefs_status says what a null ahrefs_dr means: ok (Ahrefs has no rating), partial (the domains in ahrefs_unanswered got no answer), failed or not_configured (Ahrefs did not answer; the null says nothing). ahrefs_attribution: wherever you show ahrefs_dr, show its text linked to its url next to it. errors[] lists inputs that were not valid domains.
7 + 2.5 per 100 domains, for domain_rank; ahrefs_dr adds nothing. Default 100 domains = 10 credits. Cached 7 days, or 1 hour when ahrefs_status is not ok.
Parameters
| Parameter | Default and notes |
|---|---|
targets[] | Required. At most 1000. |
It also takes the common parameters max_credits and dry_run.
{
"targets": [
"example.com",
"competitor.com",
"blog.example.net"
]
}Get traffic estimates in bulk
seo_get_traffic_estimatesEstimated monthly organic and paid traffic for up to 1,000 domains in one call.
"how much traffic do these sites get", comparing a list of domains by size, checking a prospect list for reach.
- Authority, use
seo_get_domain_ratings(a tenth of the cost). - One domain in depth, use
seo_get_domain_overview.
A list. Each row has domain, organic_traffic, organic_keywords, paid_traffic. One row per input domain in the order given. null = provider has no data. A traffic figure saved before 1 November 2026 may be on DataForSEO's older traffic model: take a new baseline rather than compare across that date. errors[] lists inputs that were not valid domains.
50 + 50 per 100 domains. Default 100 domains = 100 credits. Cached 7 days.
Parameters
| Parameter | Default and notes |
|---|---|
targets[] | Required. At most 1000. |
location | Provider location name or code. Default United States. |
language | ISO 639-1 language code. Default en. |
It also takes the common parameters max_credits and dry_run.
{
"targets": [
"example.com",
"competitor.com"
]
}Get an on-page snapshot
seo_get_pageAn on-page snapshot of one URL: title, meta description, canonical, robots, headings, word count, schema types and link counts. Fetched live, free.
"check the on-page SEO of this URL", "what schema does this page use", "what jobs are on their careers page", a quick look before a crawl.
- A whole site, use
seo_run_technical_crawl. - Rankings for the page, use
seo_get_ranked_keywordswith the URL. - What the page ranks against, use
seo_get_serp.
One record with url, final_url, status, title, meta_description, canonical, robots_meta, lang, h1[], h2[], word_count, schema_types[], links_internal, links_external, images, images_without_alt; with include, links[] (text, url) and text (without nav, header and footer). null = the tag is absent.
0 credits, rate limited. Cached 1 hour.
Parameters
| Parameter | Default and notes |
|---|---|
url | Required. An http or https URL. |
include[] | Also return the page's links, its visible text, or both. At most 2. |
{
"url": "https://example.com/pricing"
}Run a technical audit
seo_run_technical_crawlCrawl a site for technical SEO issues. Slow: returns a task_id, then read the result with get_task.
"audit example.com", "crawl the site for broken links and duplicate titles", a technical health check.
- One page, use
seo_get_page. - Rankings or traffic, use
seo_get_domain_overview. - Lighthouse scores, which it does not run.
A task_id at once, because the work runs in the background. When it is done, get_task returns target, pages_requested, pages_crawled, rendered, onpage_score, status_codes (crawled pages per HTTP status), broken_links (links, not pages: one broken link in a template counts once per page), broken_resources, non_indexable (URLs blocked from indexing by robots.txt, headers or meta tags, counting linked URLs robots.txt kept the crawler from, so it can exceed pages_crawled), duplicate_titles, duplicate_descriptions, issues[] (check, pages, sample_urls[]). Results expire after 30 days.
5 credits per 100 pages; 50 per 100 pages rendered. The charge is on max_pages requested, not pages crawled. Default 1,000 pages = 50 credits.
Parameters
| Parameter | Default and notes |
|---|---|
target | Required. A domain or host. Only that host is crawled. |
max_pages | Required. Pages to crawl. Caps by plan: 1,000 on Free and Pro, 10,000 on Growth, 100,000 on Agency. At most 100000. |
render | Default false. Execute JavaScript. 10x the cost. |
include_subdomains | Default false. Follow links onto the target's subdomains too; they share max_pages. |
It also takes the common parameters max_credits and dry_run.
{
"target": "example.com",
"max_pages": 500
}