On the last morning of my Ahrefs subscription I burned through 400,000 API units before lunch. That was deliberate, since the budget resets monthly and expires with it, so the choice was spend it or lose it. But it produced something I had not expected to find useful: a log of 1,102 calls across those final two days, with the exact unit cost of each one attached.
Ahrefs documents the pricing model in one line. Rows times fields, minimum fifty units per billable request. That is accurate and almost useless for planning, because it tells you nothing about which tool will quietly consume your month. So I measured the 41 I actually used, out of roughly 130 the server exposes.
The short answer is that three tools ate 78 percent of everything, and the free and flat-rate surfaces together returned about a hundred times more rows per unit spent than the three expensive ones.
How the Billing Actually Works#
Four mechanics, and you need all four to predict a cost.
Every billable request costs at least fifty units, no matter how little comes back. Some endpoints stop there: the two Site Audit tools charged a flat 50 per call in my log no matter how many rows came back, which is why they end up so cheap per row. The row-priced endpoints, meaning most of Site Explorer and Keywords Explorer, go further and charge per row returned, multiplied by the columns you selected. And some columns cost dramatically more than others: volume, sum_traffic, keyword_difficulty and traffic_domain add roughly ten units per row each, while a middle tier including refdomains adds about five.
The arithmetic that follows is unforgiving. A request for 120 rows with three premium columns selected costs 120 times 31, which is 3,720 units. The same 120 rows without those columns costs around 120. Same query, same shape, a factor of thirty in price, entirely decided by the select parameter.
There is a fifth mechanic that only shows up under stress. During an API incident my usage counter climbed by roughly 24,500 units while not a single row arrived. Those units were later credited back, but the refund landed hours after the fact. So the counter is not trustworthy during an outage, and abandoning a run because the budget appears to be draining can be the wrong call. What is definitely wrong is retrying in a loop while the server returns internal errors.
The Measured Numbers#
Sorted by value received, cheapest per row at the top. This is from the _units field of 1,102 real calls, not from documentation.
| Tool | Calls | Units | Rows | Units/row |
|---|---|---|---|---|
| all zero-cost endpoints (Search Console, management, free DR) | 214 | 0 | 5,940 | 0 |
site-audit-page-explorer | 55 | 2,750 | 9,789 | 0.3 |
site-audit-issues | 13 | 650 | 2,249 | 0.3 |
keywords-explorer-volume-history | 32 | 2,362 | 1,181 | 2.0 |
site-explorer-domain-rating-history | 22 | 1,366 | 506 | 2.7 |
site-explorer-pages-history | 22 | 1,366 | 471 | 2.9 |
site-explorer-keywords-history | 7 | 1,232 | 308 | 4.0 |
site-explorer-refdomains-history | 22 | 4,098 | 683 | 6.0 |
site-explorer-anchors | 22 | 28,971 | 3,096 | 9.4 |
site-explorer-broken-backlinks | 30 | 3,305 | 301 | 11.0 |
serp-overview | 20 | 8,022 | 492 | 16.3 |
site-explorer-referring-domains | 37 | 136,865 | 8,348 | 16.4 |
site-explorer-all-backlinks | 15 | 40,375 | 2,125 | 19.0 |
keywords-explorer-matching-terms | 250 | 414,542 | 19,862 | 20.9 |
keywords-explorer-related-terms | 63 | 27,977 | 1,287 | 21.7 |
site-explorer-organic-keywords | 70 | 38,099 | 1,228 | 31.0 |
site-explorer-top-pages | 29 | 10,978 | 298 | 36.8 |
site-explorer-metrics-history | 7 | 12,628 | 308 | 41.0 |
keywords-explorer-overview | 6 | 4,940 | 110 | 44.9 |
gsc-anonymous-queries | 39 | 2,088 | 7 | 298 |
| all remaining tools | 127 | 16,988 | 862 | n/a |
| Total | 1,102 | 759,602 | 59,451 |
Three Tools Ate Everything#
Keyword expansion, referring domains and raw backlinks together consumed 591,782 units, which is 78 percent of the total. Everything else, all 38 remaining tools, came to 167,820.
The single worst line has a cause I can name precisely. I ran keyword expansion at a limit of 250 rows across a batch of seed terms, and a call at that limit cost 5,250 units. At a limit of 50 the same call costs 1,050 and produces the same conclusion, because rows 51 through 250 were fragments and near-duplicates I never looked at again.
Why 250? Because that is the maximum rows per request on the plan I was on. I did not choose it as an analytical decision, I reached for the ceiling because it was there. That turns out to be the most expensive habit available, and it got worse in April when Ahrefs raised the row caps across all tiers. Lite went from 10 rows to 100, Standard from 25 to 250, Advanced from 100 to 500. An explicit limit: 50 in your code is unaffected by that change. What is affected is any call that passes no limit, any call that asks for the current maximum, and any call that used to hit the old cap and now returns up to ten times more rows for up to ten times the price.
The Other Side of the Ledger#
Everything tied to a verified project of your own is free or close to it.
Every Search Console endpoint I used cost zero, with one exception I come back to below. Together with the management endpoints and the free domain rating lookup, 214 calls returned 5,940 rows for nothing, and for domains I own those rows are more honest than the paid estimates, because they are measured rather than modelled. Site Audit is nearly as good: both audit endpoints bill a flat 50 units per request regardless of how many rows come back, which worked out to 0.3 units per row across nearly 10,000 pages, with more than twenty technical fields per URL.
Set the two groups next to each other. The free and flat-rate surfaces together returned roughly 18,000 rows for 3,400 units, which is 5.3 rows per unit. The three expensive tools returned 30,000 rows for 592,000 units, or 0.05 rows per unit. That is a ratio of about 103 to 1. The comparison only works for the combined group, because the genuinely free endpoints have no per-unit rate at all.
That ratio is the whole argument. Not "use fewer calls" but "use the other tools first", because in most cases they answer the same question.
Three Places the Common Numbers Are Wrong#
Measuring turned up three costs that do not match what gets repeated in guides, including in my own notes before this.
serp-overview is widely quoted at around 180 units per keyword. Across my whole log it averaged 401 units per call, and a separately measured call for a fresh term at limit: 20 came in at about 544. The gap between those two numbers is most likely cached repeats pulling the average down, which is exactly why an average is the wrong number to budget with. Plan a competitive SERP sweep at 544 per term, so twenty terms is around 11,000 units and not the 3,600 the common figure implies.
gsc-anonymous-queries is the worst value in the entire toolkit for a small site, and its name hides that. Everything else with a gsc- prefix is free, so it reads as free. It is not: the documented floor is 50 units per call, and measured it averaged 53.5. Thirty-nine calls returned seven rows in total, because the small sites in my sample never crossed the anonymisation threshold that endpoint exists to reveal. On a large client domain it may well pay for itself. Before using it at scale, spend one call and see whether anything comes back.
site-explorer-metrics-history costs about 1,804 units per call, which makes it one of the most expensive requests in the toolkit, though not the outright worst: site-explorer-referring-domains averaged 3,699 per call. The four individual history endpoints, domain rating, pages, referring domains and keywords, cost between 2 and 6 units per row and together average around 486 units, which is roughly a quarter of the bundled call for nearly the same story.
The Rule That Matters More Than Any of This#
Cost discipline is the small lesson. Here is the expensive one.
An early pass of one keyword analysis reported just under half a million reachable monthly searches. It was a real number produced by real API calls, and it was garbage. Keyword expansion drags in fragments and generic words, so single prepositions and bare nouns were sitting in the list being counted as opportunities.
Second attempt, filtered to terms carrying a location: roughly a fifth of the original. Better, still wrong. The top of that list was pure place names, which are travel searches with no commercial intent whatsoever.
Only a double filter produced something defensible. A term had to carry both a location and a signal of what was actually being sold. What survived was about a fifteenth of the first figure, a low five-figure monthly volume across roughly a hundred terms, and it was the first honest number in the sequence.
A volume sum over an unfiltered keyword list is not a number, it is a claim wearing a number's clothing. And it is dangerous precisely because it survives review: it came from an API, it has no rounding, it looks like data. Nobody questions a figure with six digits and no rounding. Before you sum anything, every row has to pass one test. Would a person searching this become a customer? If you cannot answer that per row, do not add the column up.
Six Rules I Would Give My Past Self#
Set limit: 50 as the default on keyword expansion and raise it only when a result visibly clipped at the boundary and the extra rows change a decision.
Exhaust the free surfaces first. Search Console for every connected project, the free domain rating lookup, management endpoints, rank tracker. On your own domains these are not the cheap option, they are the better data.
Reach for the flat-rate audit tools before the row-priced ones. Fifty units for up to 250 rows with twenty-plus fields each is the best value in the product by a wide margin.
Strip premium columns unless a decision depends on them. Ten units per row each, and intent columns in particular tell you what the words already say.
Calculate instead of estimating before any block large enough to hurt. My own threshold is 20,000 units, which is arbitrary but forces the arithmetic: rows times one, plus ten per premium column, plus five per middle column. It takes a minute and it is the difference between a planned spend and a surprise.
Put the brake in the script, not in your head. A budget check before each block that aborts below a reserve you set in advance. I wrote mine after the fact, which is exactly the wrong order and the reason this article has such precise numbers in it.
What Happens Now#
I did not renew the subscription. The measurement above is part of why: once you can see which surfaces carry the value, it becomes obvious that Search Console covers most of what I needed for my own domains, and that the paid index was earning its keep on exactly two jobs, competitor backlink profiles and search volume for terms I do not rank for yet.
That is a specific conclusion for a specific situation and I would not generalise it. What does generalise is the method. Every Ahrefs response carries its real cost inline. Log that field, group by tool, divide by rows returned, and you will know more about your own usage than any pricing page can tell you. Two days of doing it taught me more than a year of not doing it, and I only did it at the end, when the answer could no longer change what I bought.
If you are still on a plan, do it now.
The full per-tool table, the traps and the bearer-token caller I used are published at ahrefs-mcp-kit, MIT licensed.
