Competitor Keyword Gap Tool · Semrush/Ahrefs Alternative · Apify
Competitor Keywords & Keyword Gap — Semrush/Ahrefs Alternative avatar

Competitor Keywords & Keyword Gap — Semrush/Ahrefs Alternative

Pricing

from $3.00 / 1,000 gap keywords

Go to Apify Store
Competitor Keywords & Keyword Gap — Semrush/Ahrefs Alternative

Competitor Keywords & Keyword Gap — Semrush/Ahrefs Alternative

Find the Google keywords your competitors rank for and you don't: one row per keyword with every competitor's position side by side, an opportunity score and quick wins. Also lists any site's ranked keywords and its organic competitors. 88 countries, pay per row.

Pricing

from $3.00 / 1,000 gap keywords

Rating

0.0

(0)

Developer

Muhamed Didovic

Muhamed Didovic

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Features

Limited permissions

Share

Competitor Keywords

Find the Google keywords your competitors rank for and you don't. Compare your site with up to five competitors and get one row per keyword with every competitor's position side by side, an opportunity score from 0 to 100, and a quick-win flag for keywords where you sit on page two and a competitor holds the top three.

The same actor also lists every keyword any site ranks for, finds your organic competitors, and tracks your live Google position for a keyword list with the change since your last run. 88 countries, no Semrush or Ahrefs subscription, and you pay per row.


Why use this actor?

  • One row per keyword, not one per pair. With three competitors you get one row for "check backlinks", showing { "semrush.com": 2, "ahrefs.com": 1 } next to your own position. You don't have to join three exports yourself.
  • Sorted by what is worth doing. Every gap row carries an opportunityScore built from search volume, keyword difficulty, CPC and how many competitors already rank. The best opportunities come first.
  • Quick wins called out. Keywords where you rank 11-20 and a competitor ranks 1-3 are flagged with isQuickWin, and listed first if you want.
  • Brand terms left out. "semrush login" is not a keyword moz.com can win. Keywords containing any compared site's name are dropped, and the log tells you how many.
  • No competitor list needed. Leave it empty and the three sites that share the most keywords with yours are picked for you. YouTube, Reddit and other giants that share keywords with everyone are skipped.
  • A rank tracker you schedule. Track mode checks live Google results for your keywords and compares each run with the previous one: up, down, new, lost, and a flag when Google starts ranking a different page of yours. Your competitors' positions come from the same results at no extra cost, along with whether an AI Overview appears and whether it cites you.
  • Pay for rows you get. Filters run before the data is fetched, and the row limit is also what we request, so rows you filtered out are never billed.

Overview

This actor is for SEO teams, agencies, content strategists and founders who want competitor keyword data without a monthly SEO-suite seat. Gap, rankings and competitors modes read Google organic ranking data from DataForSEO Labs for the country and language you choose. Track mode reads live Google results at the moment of the run.

It writes to one dataset with a type on every row:

typeProduced byOne row per
gapKeyword gap modekeyword where a competitor beats you
rankingRankings modekeyword a site ranks for
competitorCompetitors modecompeting site
trackingTrack modekeyword checked in live Google results
overviewGap, rankings and competitors modessite looked up (keyword counts, traffic, traffic value)

The Console shows a separate table view for each type.


Supported inputs

The actor works from domains, not URLs. Anything around the domain is removed, so https://www.moz.com/blog?ref=x becomes moz.com. Subdomains are kept as given: blog.hubspot.com is analysed as that subdomain.

ModedomaincompetitorDomains
Keyword gapyour site0-5 competitors (empty = top 3 picked for you)
Rankingsfirst siteup to 24 more sites
Competitorsyour sitenot used
Trackyour siteup to 10 sites whose positions are read off the same results

Track mode also needs keywords: the searches to check, up to 1,000 per run.

Not supported: single-page (URL-level) analysis, paid search (ads) keywords, and countries without Google ranking data (the Country list only shows the 88 that have it).


Use cases

WhoWhat they do with it
Content teamsTurn missing gap keywords into the next quarter's article plan
SEO agenciesRun a gap for a prospect against their three biggest rivals for a sales deck
In-house SEOWork through isQuickWin rows: pages already on page two that need a push
FoundersSee which sites Google treats as your real competitors, which are not always the ones you expect
PPC teamsFind high-CPC keywords competitors get for free through organic rankings
Data teamsFeed rankings for a portfolio of sites into a dashboard or warehouse
Site ownersSchedule track mode weekly and get a rank report with what moved since last week
Content teamsSee which keywords show an AI Overview and whether it cites you

How it works

How it works

  1. You give a domain, an optional competitor list, a country and a row limit.
  2. The actor checks your spending limit and trims the request to what it can pay for, before anything is fetched.
  3. It looks up each site's ranking footprint (the overview row).
  4. For a gap, it fetches what each competitor ranks for that you don't, and what you both rank for, filtered by volume and the competitor's position.
  5. It merges everything into one row per keyword, drops brand terms and keywords you already lead on, scores the rest and saves them best first.

Track mode skips steps 3-5. It checks each keyword in live Google results to the depth you pick, finds your site and your competitors on that page, compares with the positions saved from your last run, and saves the new positions for next time.


Input configuration

FieldTypeDefaultWhat it does
modestringgapgap, rankings, competitors or track
domainstringrequiredThe site to analyse, e.g. moz.com
competitorDomainsarray[]Gap: up to 5 competitors. Rankings: up to 24 extra sites. Track: up to 10 sites to read positions for
keywordsarray[]Track only: the searches to check, up to 1,000
trackDepthinteger30Track only: how many Google results to check, 10, 20, 30, 50 or 100 (others round up). Billed per 10
devicestringdesktopTrack only: desktop or mobile
trackingNamestringemptyTrack only: keeps a separate history for a second keyword list on the same site
countrystringusTwo-letter country code with Google ranking data
languagestringautoLeave empty for the country's main language
maxKeywordsinteger500Rows per site (rankings), gap rows (gap, at least 50) or competitors (max 100). 1-3,000
minSearchVolumeinteger0Skip keywords with fewer monthly searches
maxCompetitorPositioninteger20Gap only: a competitor must rank at or above this position
excludeBrandTermsbooleantrueDrop keywords containing a compared site's name
includeQuickWinsbooleantrueGap only: list quick wins first

Keyword gap against named competitors

{
"mode": "gap",
"domain": "moz.com",
"competitorDomains": ["semrush.com", "ahrefs.com"],
"country": "us",
"maxKeywords": 500,
"maxCompetitorPosition": 10
}

Keyword gap, competitors picked for you

{ "mode": "gap", "domain": "moz.com", "minSearchVolume": 100 }

Track your positions weekly (schedule this)

{
"mode": "track",
"domain": "moz.com",
"keywords": ["seo tools", "domain authority checker", "link explorer"],
"competitorDomains": ["semrush.com", "ahrefs.com"],
"trackDepth": 30,
"country": "us"
}

Rankings for several sites

{
"mode": "rankings",
"domain": "backlinko.com",
"competitorDomains": ["neilpatel.com"],
"maxKeywords": 1000,
"minSearchVolume": 100
}

Find competitors in the UK

{ "mode": "competitors", "domain": "moz.com", "country": "gb", "maxKeywords": 25 }

Output overview

A gap row has your position (null when you are not in the top 100), the best competitor's position and page, every competitor's position in competitorPositions, how many of them rank, the keyword's volume, CPC, difficulty and intent, and the score and quick-win flag. gapType is missing when you don't rank at all and behind when you rank below a competitor.

A ranking row has the site's position, ranking URL and page title, the change since the last check, estimated monthly traffic and what that traffic would cost in ads, the keyword's metrics, and the SERP features shown for the keyword.

A competitor row has how many keywords the competitor shares with your site, that overlap as a share of your keywords, its average position on them, and its own total keywords and traffic.

A tracking row has your organic position (null when you are not in the results checked), the position counting AI Overviews and other blocks above it, the ranking page, the previous run's position, the change and its direction, urlChanged when Google now ranks a different page of yours, every competitor's position on the same results, the SERP features shown, and whether an AI Overview appears and cites you.

An overview row per site gives total ranked keywords, top-3, top-10 and page-two counts, estimated traffic, traffic value, and keywords gained and lost.


Output samples

Real rows from runs on 2026-10-28, US market. Trimmed where marked.

Gap row (moz.com vs semrush.com and ahrefs.com)

{
"type": "gap",
"keyword": "check backlinks",
"gapType": "behind",
"opportunityScore": 73,
"isQuickWin": true,
"yourDomain": "moz.com",
"yourPosition": 14,
"yourUrl": "https://moz.com/link-explorer",
"bestCompetitor": "ahrefs.com",
"bestCompetitorPosition": 1,
"bestCompetitorUrl": "https://ahrefs.com/backlink-checker",
"competitorsRanking": 2,
"competitorsChecked": 2,
"competitorPositions": { "semrush.com": 2, "ahrefs.com": 1 },
"searchVolume": 90500,
"cpc": 7.17,
"keywordDifficulty": 51,
"searchIntent": "informational",
"competitionLevel": "LOW",
"trendYearlyPct": 812,
"country": "us",
"language": "en"
}

Ranking row (backlinko.com, trimmed)

{
"type": "ranking",
"domain": "backlinko.com",
"keyword": "reddit popularity",
"position": 2,
"url": "https://backlinko.com/reddit-users",
"title": "Reddit User and Growth Stats (Updated)",
"previousPosition": 4,
"positionChange": "up",
"estimatedTraffic": 14661
}

Competitor row (moz.com, UK, trimmed)

{
"type": "competitor",
"domain": "moz.com",
"competitor": "semrush.com",
"sharedKeywords": 3112,
"overlapPct": 57.2,
"avgPositionOnShared": 10.6,
"trafficOnShared": 30514,
"competitorTotalKeywords": 23290,
"competitorTotalTraffic": 400289
}

Tracking row (moz.com, "seo tools", 2026-10-30, trimmed)

{
"type": "tracking",
"domain": "moz.com",
"keyword": "seo tools",
"position": 3,
"absolutePosition": 5,
"url": "https://moz.com/free-seo-tools",
"previousPosition": null,
"change": null,
"positionChange": null,
"competitorPositions": { "semrush.com": 12, "ahrefs.com": 8 },
"serpFeatures": ["ai_overview", "people_also_ask", "product_considerations", "paid", "related_searches"],
"hasAiOverview": true,
"citedInAiOverview": false,
"depth": 30,
"device": "desktop",
"checkedAt": "2026-10-30T17:07:23.315Z"
}

This was the first check, so there was nothing to compare with. From the next run on, previousPosition, change (places gained, negative for a drop) and positionChange are filled.

Overview row (moz.com, trimmed)

{ "type": "overview", "domain": "moz.com", "rankedKeywords": 22778, "top10Keywords": 7249, "estimatedTraffic": 261386 }

Key output fields

Gap: keyword, gapType, opportunityScore, isQuickWin, yourPosition, yourUrl, bestCompetitor, bestCompetitorPosition, bestCompetitorUrl, competitorPositions, competitorsRanking, competitorsChecked

Rankings: domain, keyword, position, url, title, previousPosition, positionChange, estimatedTraffic, trafficValueUsd, serpFeatures, isFeaturedSnippet

Competitors: competitor, sharedKeywords, overlapPct, avgPositionOnShared, trafficOnShared, competitorTotalKeywords, competitorTotalTraffic, competitorTrafficValueUsd

Keyword metrics (gap and rankings): searchVolume, cpc, keywordDifficulty, searchIntent, competitionLevel, trendYearlyPct

Tracking: keyword, position, absolutePosition, url, title, previousPosition, change, positionChange (up|down|same|new|lost), previousCheckedAt, urlChanged, competitorPositions, serpFeatures, hasAiOverview, citedInAiOverview, isFeaturedSnippet, depth, device, checkedAt, googleUrl

Overview: rankedKeywords, top3Keywords, top10Keywords, page2Keywords, estimatedTraffic, trafficValueUsd, newKeywords, lostKeywords

Every row: type, country, language


Pricing

Pay per event, no subscription:

EventPriceWhen
Run start$0.02once per run
Site lookup$0.02per site looked up (yours plus each competitor)
Ranked keyword$0.002per ranking row
Gap keyword$0.003per gap row
Competitor$0.005per competitor row
Rank check$0.005track mode: per keyword, for each 10 results checked

overview rows are included in the site lookup. A gap of moz.com against two competitors returning 500 keywords costs $0.02 + 3 × $0.02 + 500 × $0.003 = $1.58. 1,000 ranked keywords for one site cost $2.04. Tracking 100 keywords to the top 30 costs $0.02 + 100 × 3 × $0.005 = $1.52 per run; to the top 10, $0.52.

If your maximum cost per run can't cover everything you asked for, the actor fetches only the rows it can bill and says so in the log. If it can't cover even one row (50 rows for a keyword gap), it stops before charging anything.

Free Apify plan: 100 rows per run, one site in rankings mode, one competitor in a gap, 10 keywords to the top 10 with one competitor in track mode, 5 runs per 24 hours. Prices are the same.


FAQ

What does "missing" vs "behind" mean?

missing: at least one competitor ranks and you are not in the top 100. behind: you rank, but at least one competitor ranks higher. Keywords where you beat every competitor are left out, because they are not a gap.

How is the opportunity score calculated?

Search volume (log scale) counts for 40%, ease (100 minus difficulty) for 25%, the share of compared competitors that rank for 20%, and CPC for 15%. The result is rounded to 0-100. It is a sorting aid, not a forecast.

Where does the data come from?

From DataForSEO Labs, which tracks Google's top 100 organic results for a large keyword database in each country. Positions and traffic are estimates from that database, refreshed every few weeks, and will differ somewhat from what Semrush or Ahrefs show.

Why did my competitor list come back different from what I expected?

When you leave competitorDomains empty, competitors are picked by how many keywords they share with you in the chosen country. That is Google's view of your competition, and it can include publishers and tools you don't sell against. Name competitors yourself to compare with specific sites.

Why are some keywords with my brand missing?

excludeBrandTerms (on by default) drops keywords containing the name of any compared site, such as "moz pro" or "ahrefs pricing". Turn it off to keep them.

Can I analyse a single page instead of a whole domain?

No. The actor works at domain or subdomain level.

Does it cover paid search (Google Ads) keywords?

No, organic results only.

How does track mode know my last positions?

Each run saves the positions it found in a key-value store named competitor-keywords-rank-history in your own Apify account. The next run with the same site, country, language, device and trackingName reads it and fills the change fields. Nothing is kept on our side. Deleting that store starts the history over.

Why did my position jump when nothing changed on my site?

A track run is one snapshot of live Google results, and Google reshuffles them during the day and between data centres. A single check can be several places off from the next one. Look at the trend over several scheduled runs rather than one move.

Why is url empty on some tracking rows?

Google sometimes returns a result as a redirect without its page address. The site is still recognised, so position is correct, but the page is only filled in when it can be read reliably.

Why did a site come back with no rows?

There is no ranking data for it in the chosen country and language. Its overview row will have null counts, and the run's status message names it. Try the country where the site's audience is.


Support

Found a bug or want a feature? Open an issue on the Issues tab.

Additional services

Need a scheduled weekly gap report, a different export shape, or this data joined with your own? I build custom versions. Open an issue or message me through Apify.

Explore more scrapers

Full list at apify.com/memo23.


🤖 For AI Agents & LLM Apps

Compact reference for agents calling memo23/competitor-keywords through the Apify MCP server or the Apify API.

Purpose: Google organic competitor research: keyword gap (one row per keyword, every competitor's position side by side), ranked keywords per site, organic competitors, and live rank tracking for a keyword list with the change since the last run.

Minimal input (tested):

{ "mode": "gap", "domain": "moz.com", "competitorDomains": ["semrush.com"], "maxKeywords": 50 }

Output: rows tagged by type. gap: keyword, gapType (missing|behind), opportunityScore, isQuickWin, yourPosition, bestCompetitor, bestCompetitorPosition, competitorPositions {domain: position|null}, searchVolume, cpc, keywordDifficulty, searchIntent. ranking: domain, keyword, position, url, positionChange, estimatedTraffic, trafficValueUsd, searchVolume. competitor: competitor, sharedKeywords, overlapPct, avgPositionOnShared. overview: one per site, rankedKeywords, top10Keywords, estimatedTraffic. tracking: keyword, position|null, url, previousPosition, change, positionChange (up|down|same|new|lost), competitorPositions, hasAiOverview, citedInAiOverview.

Behaviors an agent should know:

  • Always set maxKeywords. Gap and ranking rows are billed per row ($0.003 / $0.002), plus $0.02 per run and $0.02 per site.
  • Empty competitorDomains in gap mode picks the top 3 competitors itself, which adds 3 site lookups.
  • Gap rows come sorted best first: quick wins first (unless includeQuickWins is false), then by opportunityScore.
  • Positions are Google top-100 only; yourPosition: null means not in the top 100.
  • A site with no data still costs its lookup and returns an overview row with null counts.
  • The run stops at the caller's maximum cost and fetches only what it can bill.
  • Track mode ({"mode":"track","domain":"moz.com","keywords":["seo tools"],"trackDepth":10}) costs $0.005 per keyword per 10 results checked. Change fields are null on the first run for a setup.

⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Semrush Holdings, Inc., Ahrefs Pte. Ltd., Google LLC or DataForSEO. All trademarks mentioned are the property of their respective owners. Semrush and Ahrefs are named only to describe what kind of tool this is an alternative to.

The data comes from a licensed third-party SEO data provider and covers public Google search results only. It contains no personal data and nothing from behind any login. Rankings, traffic and volumes are estimates. Users are responsible for using the output in line with applicable law and their own contractual obligations.


SEO Keywords

competitor keywords, keyword gap analysis, keyword gap tool, competitor keyword research, ranked keywords api, domain keywords, organic keywords checker, semrush alternative, ahrefs alternative, spyfu alternative, content gap analysis, seo competitor analysis, find seo competitors, quick win keywords, keyword opportunities, google rankings export, seo agency reporting, content strategy keywords, rank tracker, serp position checker, keyword rank tracking, dataforseo labs, Apify seo actor