Research providers
Connect optional research providers locally, control paid requests and combine keyword, domain, competitor, link and AI answer evidence with first-party data.
Research a market without replacing the evidence from your own site. Optional providers add keyword estimates, result snapshots, domain footprints, ranking pages and competitor rows. Search Console still supplies owner-verified search performance. Crawls still supply current page and technical evidence.
DataForSEO supports the broadest set of current research reports. Semrush Version 3 supports bounded keyword, domain, ranking-page and search-competitor research. Ahrefs API v3 supports those shared research reports plus attributed Domain Rating and bounded backlink evidence. The report contracts are provider neutral, so the adapters return the same evidence shape where their capabilities overlap. A report fails clearly when a selected provider does not support its operation or market.
Use the Semrush guide for the exact key, connection commands, supported reports and API-unit behavior.
Use the Ahrefs guide for connection, supported reports, Domain Rating attribution, backlink evidence and API-unit limits.
Connect DataForSEO on this computer
Create an API login and API password in DataForSEO, then run:
seo providers dataforseo connect
seo providers dataforseo status --check
The first command validates the credentials with the free account endpoint. The second command can repeat that check and show the connection state. The password is saved in the system keychain when available, with a private local file fallback. It is not stored in a project profile, report, cache entry or spend record.
Agents and CI can use environment variables without saving credentials:
export SEO_DATAFORSEO_LOGIN='your-dataforseo-login'
export SEO_DATAFORSEO_PASSWORD='api-password'
seo providers dataforseo status --check --json
Do not put these values in a repository, command history, report parameters or an issue. Remove locally saved credentials with:
seo providers dataforseo disconnect
Set local cost and work limits first
Provider calls can be charged. Inspect the current local limits and account context before running broad research:
seo providers dataforseo limits
seo providers dataforseo spend
Set hard daily and monthly limits in US dollars, plus maximum requests and requested rows per report:
seo providers dataforseo limits \
--daily-notice 1 \
--daily-limit 5 \
--monthly-limit 25 \
--requests 20 \
--rows 10000
The CLI reads current endpoint prices from the free account response, reserves estimated spend before a paid request, and records the actual provider cost afterward. Unknown or unsafe price evidence blocks paid work instead of assuming it is free. Local request and row limits also stop accidental fanout inside one report.
Cached results avoid repeating paid work during their retention window. A
report includes cache hit, miss or bypass state, observation time, estimated
cost, actual cost and provider task ids. Use refresh: true only when the
decision needs newer provider evidence.
Know what a provider request sends
The software stores provider credentials, caches, histories and spend records locally. A live provider request still sends the inputs needed for that operation directly to the provider.
| Operation | Inputs sent to DataForSEO |
|---|---|
| Keyword, result and domain research | Keywords or seeds, domains or URLs, market, location, device, filters and limits required by the report. |
| Link research | The target domain or URL, provider filters and result limits. |
| Indexed AI mention research | Target names and aliases, surface, market and result limits. |
| Fixed AI prompt observation | The full prompt, selected model, country, web search setting and output limit. |
| First-party enrichment | Selected Search Console query text or a derived research seed, only when includeExternal or includeSerps is explicitly enabled. |
First-party enrichment does not send Google OAuth tokens, Google account identity, Search Console property IDs, clicks, impressions, click-through rate, positions, or Google Analytics rows. The report keeps provider estimates and first-party metrics separate.
DataForSEO processes live inputs and responses under its
privacy policy. As of 23 July 2026,
that policy says API task data is stored for 365 days. Local cache removal and
seo providers dataforseo disconnect do not delete provider-side task data.
Use seo reset --yes to remove saved credentials, local configuration, caches,
histories, spend records, logs and saved reports. Environment credentials
remain under the control of your shell or runtime.
Local DataForSEO, Semrush and Ahrefs file imports are different. They are read from disk and are not uploaded to a provider or the project maintainer.
Discover the research reports
The normal CLI and MCP discovery flow exposes the same reports:
seo reports list --category opportunities --json
seo reports describe competitive-opportunities --json
seo reports describe domain-overview --json
seo reports describe competitor-keyword-gap --json
seo reports describe ai-mention-research --json
seo reports describe ai-prompt-observations --json
Run a report through the existing catalog command. There are no separate provider-named report commands.
seo reports run domain-overview \
--params '{"domain":"example.com","countryCode":"GB","languageCode":"en"}' \
--json
seo reports run competitive-opportunities \
--params '{"target":"example.com","seeds":["seo reporting software"],"countryCode":"GB","languageCode":"en","keywordProvider":"semrush","serpProvider":"dataforseo"}' \
--json
seo reports run serp-competitors \
--params '{"keywords":["blue widget","red widget"],"targetDomain":"example.com","countryCode":"GB","languageCode":"en"}' \
--json
The existing link-evidence report accepts a live Ahrefs or DataForSEO target
through the direct seo links command. It does not add another report or MCP
tool.
The current domain research endpoints use country and language. They do not
accept a city, postcode or device. Use serp-results when you need a current
location and device-specific result snapshot.
Use ranked-keyword exports without API access
You can run four domain research reports from local DataForSEO, Semrush or Ahrefs exports. No provider connection or paid request is needed. The report still uses the same typed rows and evidence rules as the live API path.
Put the report parameters in a JSON file when the file paths make the command hard to read:
{
"target": "example.com",
"countryCode": "GB",
"languageCode": "en",
"researchFiles": [
{
"dataset": "ranked-keywords",
"file": "./exports/example-keywords.csv",
"provider": "semrush",
"exportedAt": "2026-07-20T12:00:00Z",
"columns": {
"keyword": "Search Term",
"url": "Destination",
"position": "Current Rank",
"searchVolume": "Monthly Demand"
}
}
]
}
Run it through the normal report catalog:
seo reports run ranked-keywords \
--params-file ./ranked-keywords-run.json \
--json
The importer accepts CSV, TSV, JSON arrays, JSONL and NDJSON. It detects UTF-8,
UTF-16, comma, semicolon and tab-separated files automatically. This includes
Ahrefs downloads that use UTF-16 and tabs despite having a .csv name. You do
not need to convert the file first.
Each current ranking needs a keyword, an absolute HTTP or HTTPS ranking URL,
and a positive position. The importer also recognises common export names such
as Query, Phrase, Current URL, Landing Page, Current Position,
Search Volume, Volume, Difficulty, KD, CPC, Competition,
Keyword Intents, Current organic traffic and Traffic.
Leave columns out when those common headings match. Add it when an export
uses different names. A named mapping overrides automatic matching for that
field. The accepted canonical fields are keyword, url, position,
absolutePosition, searchVolume, keywordDifficulty, cpc,
paidCompetition, intent, resultCount, estimatedTraffic, resultType
and searchVolumeUpdatedAt.
Copy source headings exactly. The importer rejects missing headings and stops one source column from being assigned two meanings. This avoids treating a percentage as a visit count or a previous position as the current rank.
An export can contain separate organic and search-feature rows for the same
keyword and page. ranking-pages counts that as one ranked keyword. Its ranking
buckets and estimated traffic keep both result rows because each one describes
a different search appearance. Those totals can be higher than the unique
keyword count without being duplicates.
Set countryCode and languageCode to the market used for the export. The
file does not carry enough consistent metadata for the importer to verify that
choice. Keep every file in one run on the same market. Ambiguous fields stay
missing. For example, Traffic % is not treated as estimated monthly visits.
Use a YYYY-MM-DD date or an ISO timestamp with a timezone for exportedAt.
The same input works with these reports:
| Report | What the file supplies |
|---|---|
ranked-keywords | Ranked terms, URLs, positions and any optional metrics present in the export. |
ranking-pages | Page groups, retained keyword counts and repeated URL patterns calculated from the imported rows. |
serp-competitors | Repeated domains across the requested terms when the files contain more than one domain. |
competitor-keyword-gap | Site and competitor rows from up to four exports from the same provider. |
The gap report calls a term relevant only when at least two meaningful words
also appear together in one retained Search Console query. Common words such as
new, search, page and tool do not count. A one-word match stays weak,
words found across separate queries are not combined into stronger evidence,
and search operators such as site: and filetype: are ignored.
domain-overview still requires a live provider. A ranked-keyword export
cannot safely recreate the provider’s full domain totals, traffic estimate or
movement history.
Pass one to four files from the same provider. Separate files are useful for a site and up to three competitors. A single run can normalize at most 100,000 rows across all files. CSV, TSV, JSONL and NDJSON files are capped at 50 MB each. Regular JSON arrays are capped at 10 MB because they are loaded as one value.
Every file gets its own entry under evidence.imports. That entry records the
provider, export time, detected encoding and delimiter, SHA-256 file hash,
included fields, explicit column mapping, bytes read, total file rows, supplied
rows, valid rows, filtered historical rows, rejected rows, duplicates and row
cap. Ahrefs
comparison rows with no current URL or position are filtered historical rows,
not broken records. The report scans a bounded file to finish its hash and
file-row count even when the row cap stops normalization. Missing rows remain
unknown because a local export does not prove full provider coverage.
Research indexed AI mentions and citations
ai-mention-research checks one named target in a provider-indexed set of AI
answers. It can compare up to five named competitors in the same dataset,
return cited domains and bounded question samples, mark citations from an
owned domain, and compare sample wording with retained Search Console queries.
seo reports run ai-mention-research \
--params '{"target":{"label":"Example Analytics","aliases":["Example"]},"competitors":[{"label":"Competitor Cloud"}],"domain":"example.com","surface":"google-ai-overview","countryCode":"GB","languageCode":"en","location":{"code":2826},"site":"sc-domain:example.com","sampleLimit":10}' \
--json
The default path makes two paid live API requests: one for metrics and one for
question samples. Set includeSamples to false for a metrics-only run with
one paid request. The report accepts one location and language per run, at most
five competitors, at most five aliases per target, and at most 25 retained
samples. Cached results use the local provider cache and do not repeat paid
work until their retention window expires unless refresh is true.
DataForSEO currently supports Google AI Overview and ChatGPT mention records.
Its ChatGPT data is limited to United States English, so use country code US,
language code en, and US location code 2840 for that surface. Other market
combinations fail before a paid request.
Read the result in this order:
dataStatus, exact surface and market, source status, coverage, cache, cost, task ids, and warnings.- Provider metrics for each target, then
targetComparisonShare. That share describes only the supplied comparison set. - Question samples, observation dates, model, answer truncation, cited URLs,
and
ownedSources. - Optional Search Console source limits and each sample’s bounded lexical matches.
- Repeated question patterns, data-source briefs, findings, caveats, and next steps.
Provider-indexed records are not live prompt observations or a complete census.
Mention count and AI search volume do not prove traffic, sentiment, citation
quality, authority, future visibility, or demand for a new page. Search Console
overlap is a lexical heuristic over retained rows. Run
ai-prompt-observations when the current answer would change the decision.
For programmatic SEO, repeated question terms can reveal a useful research direction. They do not approve a template. Confirm shared intent, existing page coverage, data rights, stable identifiers, fields, geographic coverage, update frequency, missing values, duplicates, useful page variation, and representative output before increasing page count.
Record current AI answers for fixed prompts
ai-prompt-observations runs one to five fixed prompts across one to four
explicit current models from ChatGPT, Claude, Gemini, or Perplexity. The full
set of prompt and model combinations is capped at 20 paid live requests. Start
with one prompt and one model, then add only observations that can change a
decision.
seo reports run ai-prompt-observations \
--params '{"prompts":[{"id":"analytics-tools","group":"commercial","prompt":"Which privacy-friendly analytics tools suit a small publisher?"}],"models":[{"surface":"chatgpt","model":"current-model-name"}],"target":{"label":"Example Analytics","aliases":["Example"],"domains":["example.com"]},"competitors":[{"label":"Competitor Cloud"}],"countryCode":"GB","languageCode":"en","site":"sc-domain:example.com"}' \
--json
The requested model is the exact model you chose. The effective model is the model the provider says actually ran. Fan-out queries are extra supporting searches the provider reports using to form the answer. Keeping these fields separate prevents a provider-side model change from looking like a visibility change.
Model names are exact. Before paid work, the report checks the provider’s free
current model catalog. A retired or misspelled model fails with current choices
and confirms that no paid request started. This avoids silently moving a saved
prompt set to a new model. Perplexity always uses web search. Other models must
advertise web-search support when webSearch is true.
Read the result in this order:
dataStatus, warnings, request count, provider, market label, and optional Search Console status.- Each observation’s coverage, cache state, requested and effective model, checked time, answer, citations, token use, task id, and exact returned cost.
- Named-target matches and cited domains. These describe only the retained answer and the aliases or domains you supplied.
- Comparison status. Only a fresh, complete, untruncated observation with the same provider, prompt, requested and effective model, market label, web-search setting, and output-token limit supports a change.
- Supporting-search themes in
fanOutThemes, optional Search Console overlap, findings, caveats, and next steps.
The preflight estimate contains provider base fees only. The response records the exact task cost after token and web-search charges are known. If any request fails, actual total cost stays partial or unknown instead of pretending the missing request cost zero. Cached results do not support a new change claim.
Answers and bounded history stay in the local SQLite store. The history keeps at most 90 observations per exact configuration, 10,000 observations in total, and 128 MB of logical payload. Answers are capped at 24 KB, citations at 25, fan-out queries at 20, and structured agent output at the shared 96 KB budget.
The country and language fields label and separate a fixed prompt set. AI response endpoints do not expose identical location or language controls across every surface, so prompt wording remains the direct language instruction. One answer is not a universal result, visibility score, assistant ranking, or proof that a target never appears.
Supporting-search themes and Search Console word matches are bounded research leads. Before planning a programmatic template, validate keyword demand, current search-result intent, existing page coverage, source rights, stable identifiers and fields, geographic coverage, update frequency, missing values, duplicates, useful page variation, and representative output. No new page remains a valid result.
Start a local search investigation with first-party evidence
local-search-demand finds retained Search Console queries whose wording
contains an explicit place name, nearby phrase, UK postcode or a US ZIP code
with supporting local wording. Add the real place names, aliases and known ZIP
codes for the market because automatic detection is deliberately conservative.
seo reports run local-search-demand \
--params '{"site":"sc-domain:example.com","locationTerms":["london","manchester"],"days":90}' \
--json
The default path makes one bounded Search Console request and no paid provider request. It returns the local query and landing-page evidence, filtered-row counts, action labels and repeated URL patterns. The patterns are prompts to inspect working local page families, not proof that more pages should exist.
Request live context only for a short decision-critical set:
seo reports run local-search-demand \
--params '{"site":"sc-domain:example.com","locationTerms":["london"],"includeSerps":true,"countryCode":"GB","languageCode":"en","location":{"name":"London,England,United Kingdom"},"device":"mobile","serpLimit":3}' \
--json
That path adds at most three current organic snapshots through the same cache,
spend limits and provider-neutral result contract as serp-results. Read the
recorded location, device, observation time, coverage, cache and cost for every
snapshot. The report also groups recurring organic domains as unclassified
search competitors and retains bounded local-pack listing rows with their
observed rank, title, URL, phone, rating and provider identifier when returned.
These rows do not prove listing ownership, complete Maps coverage or Google
Business Profile performance.
Add optional visitor geography only when it would change a landing-page or template decision:
seo reports run local-search-demand \
--params '{"site":"sc-domain:example.com","locationTerms":["london","manchester"],"googleAnalyticsPropertyId":"123456789","analyticsLimit":5000}' \
--json
This makes one bounded Google Analytics request for landing page, country, region, city and sessions. Query strings are removed from the landing-page dimension before an exact path join. Unmatched, missing, malformed, duplicate, capped and quality-warning states stay visible. The returned geography describes measured sessions for retained landing pages. It does not establish which Search Console query produced a session.
A place in the query does not prove the searcher’s physical location. Search Console average position is not an exact local rank. Keep query wording, landing-page geography and exact live results separate when deciding whether to improve a current page, review overlapping pages or investigate a new local template.
Review live referring-link evidence
Run the bounded provider path for a domain:
seo links --provider dataforseo --target example.com --json
Add a Search Console property when you own the target and want first-party page evidence in the same result:
seo links --provider dataforseo --target example.com \
--search-site sc-domain:example.com --json
The default run makes one summary request, then requests up to 100 live
representative backlinks with one row per referring domain. --row-limit can
raise that bounded request to 500. It does not fetch every backlink or fan out
across every target page. Both requests run sequentially, use the local
provider cache, and pass through the same report spend limits as keyword and
domain research.
Read these result areas in order:
dataStatus, warnings, caveats and source provenance.providerSummaryfor current provider counts and named metrics.providerEvidencefor coverage, filters, cache, cost and observation time.findingsandtargetContextfor saved-crawl and Search Console evidence.targetCountsand the bounded representativelinkslist.
A matching saved crawl can flag linked targets observed with an error response, redirect, conflicting canonical or non-indexable state. Search Console can add retained clicks and impressions for the same target. Those sources stay separate: a provider row does not prove link quality, a missing Search Console row is not zero, and a saved crawl does not prove the page still has the same state. Open the referring URL and check the target live before acting.
Provider rank and spam metrics retain their DataForSEO names and 0 to 100 scales. They can help order a review, but they are not Google ranking factors, universal authority scores or interchangeable with another provider’s metric.
Start with first-party opportunities
Use keyword-opportunities when the question starts with your own Search
Console data. It combines quick wins, second-page evidence, query clusters,
repeated first-party URL patterns and optional provider metrics in one bounded
review queue.
Use the provider-led reports for different questions:
competitive-opportunitiesturns a topic into a bounded keyword and competitor investigation order with current results and optional link context.domain-overviewgives a quick country-level estimated footprint.ranked-keywordsopens bounded keyword and ranking-page rows.ranking-pagesfinds pages behind the footprint and repeated path patterns.serp-competitorsfinds domains that recur across an explicit keyword set.competitor-keyword-gapcompares up to three relevant competitors with retained Search Console themes and the provider footprint for your site.
Pass a Search Console property only when it matches a site you own. Competitor domains stay provider-only. The report never pretends to have first-party evidence for somebody else’s site.
Classify competitors before comparing gaps
A recurring result domain can be a publisher, directory, community,
marketplace or business. serp-competitors leaves undeclared site types as
unknown. Review those domains, then pass a small relevant set to
competitor-keyword-gap.
The gap report does not label every competitor term an opportunity. It keeps four states separate:
- Already observed in retained Search Console rows.
- Already ranked in the provider footprint for the site.
- Relevant gap candidate based on bounded first-party theme overlap and competitor evidence.
- Unverified competitor term.
An absent Search Console row means only that the bounded retained data did not contain it. Search Console can omit anonymised queries, and row caps or the date range can hide evidence.
Review programmatic SEO patterns carefully
Ranking pages and competitor gaps inspect repeated URL structures. That helps an agent find possible page families without downloading a whole domain. A path pattern does not prove shared intent, quality, useful data or that more pages should be created.
For a plausible new template, the gap report returns a bounded data-source brief. Check:
- stable identifiers, fields, units and geographic coverage;
- update frequency, missing values, duplicates and malformed records;
- access rights, attribution, rate limits and local cache retention;
- the useful information that makes each generated page distinct;
- representative sparse, stale and boundary records before scaling.
For an existing first-party template, run pseo-audit before adding variants.
For a new family, inspect current results and representative competitor pages,
then complete the data-source research before implementation.
Read each source by what it can establish
Provider volume, difficulty, traffic, intent and visibility are estimates. Search Console clicks and impressions are first-party measurements for the selected property and dates. A crawl observes the current site version. A live result report observes one query, market, device and time.
Useful analysis can combine these sources, but it should not blend their numbers into one unexplained score. Read source coverage, request filters, observation dates, cost, warnings and caveats before the findings. Verify a shortlisted keyword with current results before changing content or a programmatic template.