Competitor Keywords Scraper — Ranked Keywords of Any Domain
Pricing
from $1.50 / 1,000 ranked keywords
Competitor Keywords Scraper — Ranked Keywords of Any Domain
The keywords any domain or page ranks for on Google — position, ranking URL, search volume, CPC, keyword difficulty, search intent and estimated traffic for each, in 94 countries. From $1.50 per 1,000 keywords plus a $0.02 lookup per domain; a domain that ranks for nothing is never charged.
Pricing
from $1.50 / 1,000 ranked keywords
Rating
0.0
(0)
Developer
Steadyfetch Team
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Competitor Keywords Scraper: the keywords any website ranks for on Google, with the numbers to act on them. Give it a competitor's domain, or one page, and get back the keywords it ranks for in Google's top 100, one row each: its position, the page that ranks, monthly search volume, CPC, competition, keyword difficulty (0–100), search intent and the traffic it is estimated to bring — in 94 countries. A domain with no ranked keywords is never charged.
Using an AI agent? Pin this actor in Apify's MCP server with one link: https://mcp.apify.com?tools=steadyfetch/competitor-keywords-scraper
- Actor id:
steadyfetch/competitor-keywords-scraper - Input:
{ "domains": ["ahrefs.com"] }— the one field you have to set. Add"maxResultsPerDomain": 1000for more keywords. - Cap the bill: set
maxTotalChargeUsdon the run (a run option, not Actor input), e.g.0.50— the run stops when it reaches it, and never buys keywords it cannot sell you. - How often it changes: the source re-checks the Google results behind each ranking about every 75 days, and each row's
lastUpdatedsays when — a monthly schedule catches most moves. - Run it on a schedule: save your input as a Task and run it monthly on an Apify Schedule; from the second run on, each row says where the keyword ranked last time (
previousPosition,positionChange,isNew).
If it earned its keep, a rating helps other buyers find it, and saving the actor keeps it one click away.
See a real run before you spend anything: sample dataset — ten keywords backlinko.com ranks for in the United States from one verified run, unedited, with the domain's overview row and the run's own summary row last: ten keywords delivered and charged, plus one lookup.
Just want to see it work? Click Start with nothing set and the run gets ten ranked keywords for the example domain ahrefs.com in the United States, charged like any run. Pick a country or a limit but set no domains and that same sample runs under your settings, with one uncharged note row; a limit above ten is capped at ten. Put your own domains in Domains or pages for your own run.
Unofficial. This actor is not affiliated with, endorsed by, or sponsored by Google. "Google" is a trademark of Google LLC, used here only to describe where search data comes from.
What you get
One row per keyword the domain ranks for:
{"rowType": "keyword","domain": "ahrefs.com","targetType": "domain","keyword": "backlinks checker","position": 1,"absolutePosition": 1,"url": "https://ahrefs.com/backlink-checker","searchVolume": 90500,"cpc": 7.17,"competition": 0,"competitionLevel": "LOW","keywordDifficulty": 82,"searchIntent": "informational","estimatedTraffic": 27512,"lastUpdated": "2026-07-30T04:18:28.000Z","previousCheckAt": "2026-05-15T03:34:38.000Z","serpTrend": "same","country": "US","language": "en","previousPosition": null,"positionChange": null,"isNew": null,"previousRunAt": null,"charged": true}
| Field | What it is |
|---|---|
rowType | keyword for a ranked keyword; the overview and summary rows carry their own. |
domain, targetType | The domain or page you asked about, as it was read, and whether it was read as a whole domain or one page. |
keyword | A keyword it ranks for. |
position | Its organic position on Google, counting organic results only (1 = the top organic result). |
absolutePosition | Its place counting every element on the results page, ads and boxes included. |
url | The page of that site that ranks for the keyword. |
searchVolume | Average monthly searches over the last 12 months. |
cpc, competition, competitionLevel | Cost per click in USD, advertiser competition from 0 to 1, and LOW / MEDIUM / HIGH. |
keywordDifficulty | 0–100: how hard it is to rank in the top 10 organic results. |
searchIntent | informational, navigational, commercial or transactional. |
estimatedTraffic | Monthly visits this position is estimated to bring — search volume times the click share of the position. An estimate, never a measured count. |
lastUpdated, previousCheckAt, serpTrend | When the source last checked this results page, when it checked it before that, and how the position moved between those two checks: up, down, same or new. |
country, language | The market the keyword was read in. |
previousPosition, positionChange, isNew, previousRunAt | Where it ranked in your last run of the same domain and market, how many places it moved (a positive number means it climbed), whether it is new since that run, and when that run was. Empty (null) on your first run. |
charged | Whether this row was billed. |
A figure the source does not publish comes back null — never invented.
One overview row per domain, uncharged: how many keywords the domain ranks for in total (often
far more than you asked for), how they spread over positions 1, 2–3, 4–10, 11–20 and on down to 100,
the estimated monthly traffic they bring, and how many of its rankings are new, up or down since the
source's check before. With a position or volume filter set, those totals count only the keywords
that pass it (totalsMatchYourFilters: true). One summary row last, uncharged: the run's receipt —
what was delivered, what was charged, and what stopped the run. Rows with a missReason are uncharged
notes saying why something was not delivered.
Settings
| Setting | Field | Default |
|---|---|---|
| Domains or pages | domains | — up to 100. A bare domain or a homepage link reads the whole domain; a link with a path reads that one page |
| Country | country | US — 94 countries; a country the source does not cover is refused with an uncharged row, never swapped for another |
| Language | language | the country's main language |
| Max keywords per domain | maxResultsPerDomain | 100, up to 5,000 |
| Sort keywords by | sortBy | traffic (estimated traffic, biggest first); also volume and position |
| Ranking at or above position | maxPosition | none — set 1–100, e.g. 10 for page one only |
| Minimum search volume | minSearchVolume | none |
The filters run at the source, so a keyword outside them is never delivered or charged. The sort
decides which keywords a limit keeps: traffic gives the keywords that bring the domain the most
visits, volume the biggest searches it shows up for, position its best rankings first. Organic
Google results only.
Pricing
Pay per event, all-inclusive — no platform-usage charge on top, and no start fee.
| Event | Apify free plan | Bronze | Silver | Gold and above |
|---|---|---|---|---|
| Ranked keyword (per keyword delivered) | $0.003 | $0.0025 | $0.002 | $0.0015 |
| Domain lookup (once per block of up to 1,000 keywords from one domain) | $0.02 | $0.02 | $0.02 | $0.02 |
100 keywords for one domain is one lookup: $0.17 on Gold, $0.32 on the Apify free plan. 1,000 keywords is still one lookup; 5,000 is five. Ten domains at 100 keywords each are ten lookups.
Never charged: a domain or page with no ranked keywords (no lookup fee either), a keyword your filters leave out, the overview and summary rows, and a request the source refuses or cannot answer.
How often this data changes
Rankings move every day, but the source re-checks the Google results behind each ranking on its own
cycle: about every 75 days in our live reads (the middle case; from 74 to 218 days). In one read of a
large domain on 2026-10-03, its top 20 keywords had last been checked between 2026-06-17 and 2026-09-02,
and their search volumes had been refreshed in mid-September. Each row's lastUpdated says when its
result was checked, and serpTrend says how it moved since the check before — so even your first run
shows which rankings are climbing.
So the useful pattern is the same domains once a month — a monthly schedule catches most moves. A run
more often mostly returns the same positions, and every run reads the source anew and charges for what it delivers. Your own
Apify account remembers the positions each domain had, per country and language, and the next run of
the same domain fills previousPosition, positionChange and isNew from that memory: a monthly rank
tracker for your competitors, and for your own site. Keep the limit, sort and filters the same from run
to run — isNew compares against what your last run delivered, so a keyword that was only outside last
time's limit would read as new. When the sort or a filter changed, isNew stays empty;
previousPosition still comes from your last run.
Set the schedule: save your input as a Task (Actor page → Save as a new task), then add that
task to an Apify Schedule (Console → Schedules → Create) with a cron such as 0 7 1 * * for the first of
every month.
Limits are hard limits
maxResultsPerDomain and your maximum total charge stop the run exactly where they bind; the run still
finishes successfully and the last row says what was delivered and what stopped it. Keywords a request
already returned are always delivered.
On the Apify free plan, one domain lookup per account in any 24 hours is included — one domain, up to 1,000 of its keywords; past it the run stops, and that domain's uncharged overview row says when it resets. Paid Apify plans carry no daily allowance.
Steadyfetch keyword tools
| You want | Actor |
|---|---|
| The keywords a competitor's domain ranks for, with positions | this actor |
| New keyword ideas from a seed, with volume, CPC and difficulty | Keyword ideas |
| A 0–100 difficulty score for a keyword list you already have | Keyword difficulty |
| Monthly search volume and CPC for a keyword list | Keyword search volume & CPC |
| Autocomplete suggestions across 5 engines | Autocomplete keywords |
| Rising and Breakout queries with the growth number | Breakout keywords |
Feedback & support
Found an issue? Open it on the Issues tab — we usually reply within a couple of hours, always within a day.