Skip to content
Houtini.

How to do a technical SEO audit with Claude (and cut your SEO tool bill)

In today's post I'm taking a closer look at SEO Audit Console, the free, open-source MCP server I built, which pulls your crawl, Search Console and field data into a database on your own PC so that Claude can run the audit, the content research and the link work from it. By my estimate it can cut your SEO tool bill by about 90%, so I go through the npx install and the prompts I type, with output from a live run on houtini.com.

Richard Baxter Richard Baxter AI Ops & Marketing Engineer
Published Updated 23 min read
On this page
  1. What it replaces, and what it costs
  2. How SEO Audit Console works
  3. Install it with npx
  4. Connect Search Console and add the optional keys
  5. Run your first technical SEO audit
  6. From finding to fix
  7. Tools beyond the crawl
  8. Content research from your own data
  9. Top pages and competitors
  10. Link equity, internal and external
  11. Rank tracking and the portfolio
  12. The dashboard
  13. What we've used it for
  14. Where to start
SEO Audit Console's Opportunities tab on the fictional Larchmere Outfitters demo site: the quick-wins matrix plotting every query by average position and click-through rate against the expected-CTR curve, bubbles sized by impressions

When I ran an agency, our biggest cost was data collection, and then the time it took to analyse what we had collected. These days that shouldn't be a thing. SEO Audit Console is the MCP server I built to take that cost out. An MCP server is a small program that gives Claude a set of tools it can call. This one is free and open source, and it gives Claude a crawler, your Search Console data and a 143-check audit. By my estimate, Claude and this MCP can cut your SEO tool bill by about 90%, and the list prices further down let you do the sum for your own stack.

I'll go through the install, which is one npx command, then the prompts I type for a technical audit, content research, top pages and link equity, with what comes back from each and what to do with it. I run it daily on my own properties, and the run output below comes from houtini.com on 25 October 2026, with the numbers as the tool returned them.

The tool collects the data and ranks what it finds. Then there are your recommendations and your SEO strategy. But that bit's on you - you still have to think!

What it replaces, and what it costs

At the vendors' own list prices as of October 2026, Semrush starts at $139 a month on monthly billing. Ahrefs Lite is $129 a month, and Site Audit is included on that plan. Screaming Frog's SEO Spider is £199 a licence a year, or $279 on the US view of the same page. Sitebulb Lite is $18 a month, Moz Pro Standard is $99 a month, and Majestic Lite is $49.99 a month. If you pay for two or three of those, the table below sets them side by side so you can add up your own.

ToolPublished list price (October 2026)
Semrush$139, $199, $299 or $549 a month
Ahrefs$129 (Lite, includes Site Audit), $249 or $449 a month, or $1,499 a month on an annual commitment
Screaming Frog SEO Spider£199 ($279) a year per licence
Sitebulb$18 (Lite) or $42 (Pro) a month, Cloud from $125 a month
Moz Pro$49 (Starter), $99 (Standard), $179 or $299 a month
Majestic$49.99, $99.99 or $399.99 (API) a month
SEO Audit ConsoleFree, Apache-2.0
Google Search Console and the CrUX APIFree
DataForSEOPay as you go from a $50 top-up that never expires

SEO Audit Console itself is Apache-2.0: free to use, modify and redistribute, including commercially. Google Search Console is a free service, and the Chrome UX Report API is free too, at up to 150 queries a minute per Google Cloud project. The crawl, the audit, the fixes and the small local models it downloads once cost nothing per call.

You pay per call for DataForSEO, but only when you ask a question that needs it: keyword volumes, competitor pages, backlinks. DataForSEO is pay as you go, with no subscription. You top up a balance of at least $50 that never expires, and calls draw it down at fractions of a cent to a few cents each. Every response is cached for 20 days, so asking the same question again inside that window is free. My own usage runs to a few dollars a month.

How SEO Audit Console works

Under the hood it is a Node application wrapped in the MCP SDK, writing to SQLite on your own PC. Five main sources feed that database: its own crawl of your site, Search Console including URL Inspection, CrUX (the Chrome UX Report, Google's record of real Chrome users' page speed), DataForSEO and Majestic. The first three are free. The last two are optional and paid, and leaving a key empty switches its tier off. Each property gets one SQLite database, by default under Documents/seo-audit-console, alongside the caches and a reports folder. Your data stays on your machine. No telemetry.

The dashboard screenshots come from Larchmere, an invented UK outdoor-gear retailer the project uses for its demo data, starting with the Summary tab below.

The SEO Audit Console Summary tab on the fictional Larchmere demo site: 53.9k organic clicks in 28 days, 59% non-brand, site health 71/100, 218 of 260 inspected URLs indexed, a failing field Core Web Vitals check and AI readiness 31/100, above organic clicks by month

The Summary tab on the fictional Larchmere demo site, 28 days to 15 October.

When Claude answers a question about your site, it queries that database and answers from the result. The data is filtered by Claude's ability to write SQL queries - so that data played back is fact.

Putting everything in one database is also how it joins three views of your site: a crawler sees it from the outside, Search Console sees what Google did with it, and CrUX sees what happened in people's browsers. Almost every technical SEO audit I've been handed in twenty years is a crawler's opinion, and a crawler only ever sees half the picture.

Install it with npx

Claude starts the server and calls its tools, so you need either Claude Desktop or Claude Code before anything else. If you don't have an account yet, signing up for Claude through this link gives you a free week of Claude Code, while the guest passes last.

You need Node.js 20 or newer and a Search Console property you own. For Claude Desktop, add this block to claude_desktop_config.json.

{
  "mcpServers": {
    "seo-audit-console": {
      "command": "npx",
      "args": ["-y", "@houtini/seo-audit-console"],
      "env": {
        "GOOGLE_APPLICATION_CREDENTIALS": "C:/path/to/service-account.json",
        "DATAFORSEO_USERNAME": "",
        "DATAFORSEO_PASSWORD": "",
        "MAJESTIC_API_KEY": "",
        "CRUX_API_KEY": ""
      }
    }
  }
}

The first line of the env block is required; it points at the Google service-account key you create in the next section. The rest are optional: paste a key between the quotes, or leave the string empty and that tier stays off. For Claude Code it is one line.

claude mcp add seo-audit-console --env GOOGLE_APPLICATION_CREDENTIALS=C:/path/to/service-account.json -- npx -y @houtini/seo-audit-console

npx downloads the published build on first launch, and you pick up new versions without touching a terminal again. After any config change or upgrade, fully restart Claude by quitting it from the system tray, not just closing the window, because clients read the tool list once, when they connect, and keep it.

A normal npx install needs nothing more than that. If you run your MCP servers through Docker's MCP gateway, use the route built for it: a prebuilt image with longLived: true and SAC_JOB_RUNNER=external in the catalog entry, plus the seo-audit-runner container, so that the server queues each job and the runner claims it and runs it in its own long-lived process. Set up that way, the first call on a connection takes about two seconds and the rest are instant.

Then open Claude and type the first prompt.

list properties

Your properties should come back. If the list is empty, the service account almost always hasn't been added to the property yet, and the next section covers that. seo_audit_help prints the feature menu with an example prompt for every feature, so this one is worth running once.

run seo_audit_help

Connect Search Console and add the optional keys

The one required credential is a Google service account that can read your Search Console property. It is a one-time, ten-minute job, in three steps.

First, in the Google Cloud Console, create a project and enable the Search Console API. Second, create a service account, open its Keys tab, choose Add key > Create new key > JSON, and the key file downloads; that file's path is what goes in GOOGLE_APPLICATION_CREDENTIALS. Third, in Search Console go to Settings > Users and permissions and add the service account's email address, which ends .iam.gserviceaccount.com, as a user on each property you want to audit. Full user is enough for everything the tool does.

The third step is the one people miss, and until that email is on the property the account sees nothing.

Search Console's Users and permissions screen with a service account email ending .iam.gserviceaccount.com added as a user with Owner permission, the other email addresses blurred

The service account added as a user in Search Console, here with Owner permission.

DataForSEO's username and password switch on the keyword, SERP (search results page), competitor and backlink tools, cached for 20 days by default. A Majestic key only ever does anything when you run link_intersect or pull_backlinks, and its cache is 30 days. The table below lists each key and what it unlocks.

SettingWhat it switches onCost
GOOGLE_APPLICATION_CREDENTIALS (required)Search Console and URL Inspection, the crawl and the whole core auditFree
CRUX_API_KEYReal-user Core Web Vitals from the Chrome UX Report, and the four field checksFree
DATAFORSEO_USERNAME and DATAFORSEO_PASSWORDKeyword volume, intent, SERP features, competitors, top pages, rank history, backlinksPay as you go, cached for 20 days
MAJESTIC_API_KEYTrust Flow and Topical Trust Flow on link prospects and backlinksMajestic's API plan, $399.99 a month

The CrUX key is free and worth adding on day one, because field data is the best way to get INP (Interaction to Next Paint, how quickly a page responds to clicks, taps and key presses). In the same Cloud project, go to APIs & Services > Library, find the Chrome UX Report API and enable it; then on the Credentials tab choose Create credentials > API key, restrict the key to the Chrome UX Report API only, copy it into CRUX_API_KEY and restart.

Google Cloud's API restrictions dropdown filtered to the Chrome UX Report API

Restricting the free CrUX key to the Chrome UX Report API.

With the keys in, pull your data.

Refresh sc-domain:yoursite.com

A refresh is one background job that runs the Search Console sync, then the crawl, then URL Inspection, then rank history, then CrUX when the key is set. The rank-history phase is a DataForSEO call, so it runs only when those credentials are set. The sync is incremental: the first run takes the last 90 days and later runs fetch only the new days. The crawl seeds itself from links, your sitemaps and every URL Google already knows about from Search Console, which is how it reaches pages that nothing on your site links to.

Run your first technical SEO audit

Run an SEO audit on yoursite.com

The audit has 143 checks across nine categories over the joined data, locally, without calling any outside service. The table below lists the categories and the number of checks in each.

CategoryChecksWhat it looks for (examples)
Crawlability21Broken internal links, redirect chains and loops, internal links to redirects, deep pages, orphan pages, backlinked URLs that 404, AI search bots blocked
Indexation29Google ignoring your canonical, broken canonical targets, noindex on pages with traffic, index bloat, soft 404s, hreflang errors, indexable pages missing from the sitemap
On-page24Missing or duplicate titles and meta descriptions, H1s, heading order, image alt text and dimensions, broken outbound links, Discover pages missing og:image or max-image-preview:large
Content7Thin pages, near-duplicate pages, content that only survives in the raw HTML, statistical tells of generic AI text
Structured data14No structured data, JSON-LD that doesn't parse, missing required fields, articles with no author, rich-result issues Google reports
Security3Pages served over HTTP, mixed content, no HSTS header
Performance14Slow server response, real-user (CrUX) LCP, INP and CLS, field regressions, oversized or legacy-format images, render-blocking head resources
Accessibility7Links and buttons with no accessible name, unlabelled form fields, pinch-zoom disabled, duplicate ids, tabindex above zero
Merged (Search Console plus the crawl)24Striking distance, CTR below what the position should earn, cannibalisation, traffic decay, ghost pages Google ranks but the crawl can't reach, the top query missing from the title or H1

Every check carries a label. D means deterministic: the finding cites the bytes it found. G means the evidence is Google's own data, from Search Console or URL Inspection. N means judgement, a heuristic that runs only when you ask for it. By default the audit holds back every check below full certainty, so the first list you see holds only the findings the tool is sure of. To see the rest, ask for them.

Run an SEO audit on yoursite.com and include the judgement findings

The findings come back ranked by expected clicks per developer-hour: the clicks at stake in your real Search Console data, times the expected yield of the fix and the check's certainty, divided by the effort in hours. Yield is set per category, so an indexation fix is assumed to return 0.8 of the clicks at stake, a crawlability fix 0.7 and an on-page fix 0.2, with a severity multiplier on top. Findings about page experience (image weight, blocking assets, accessibility) stake a tenth of the page's clicks. That tenth is a stated assumption rather than a measurement; it changes the order only, and every finding is still reported. A check whose data was never collected isn't shown as passed: it is listed under "Not collected" with the step that collects it. On the houtini.com run that list had six entries, four of them waiting on render_pages and two on a crawl with headResources switched on.

The refresh behind that run crawled 525 URLs and saw 13,588 links. The audit returned 705 findings in 315 milliseconds: 6 critical, 46 high, 218 medium and 435 low. Finding number one was a CTR (click-through rate) problem on the Claude Desktop beginners guide: 3 clicks from 2,269 impressions at position 3.6, a 0.1% CTR against the 8% expected at that position. It priced that at 181.5 expected clicks for 3.6 hours of work, with its own note attached: near-zero CTR at that position is likely a SERP feature or navigational intent taking the clicks, so check the live SERP before rewriting the title and meta. Numbers two and three were the same check on the LM Studio set-up guide (21 clicks from 4,499 impressions at position 7.1) and the Claude Code system-requirements page (4 clicks from 3,301 impressions at 5.6).

# SEO audit - houtini.com, 25 October 2026 (run_audit, condensed)
705 findings · 6 critical · 46 high · 218 medium · 435 low
Computed in 315 ms. Top finding by expected clicks per developer-hour:
ctr-below-expected  /articles/claude-desktop-beginners-guide
  3 clicks, 2,269 impressions, position 3.6, CTR 0.1% (expected 8%)
The Issues & fixes tab on the Larchmere demo site, listing 1,532 findings ranked by impact, each with its severity, URL, clicks, impressions and an impact badge

The Issues & fixes tab on the fictional Larchmere demo site: every finding ranked by impact against effort, using the traffic at risk on each page.

From finding to fix

Generate the fix for #1

fix_finding takes a finding id and returns the artefact for it: paste-ready JSON-LD for a schema finding; a 301 rule for a redirect finding, in htaccess format by default, or nginx or Next.js; and, for an orphaned page that earns impressions, a short list of pages to link from, picked from your pages with the most internal PageRank. Checks without a generator return fix guidance instead. Everything is dry-run: it returns artefacts, it never writes to your site. That's a line I won't cross. You read the artefact and decide, then ship it through whatever deploys your site.

For URL-level questions there is probe_urls, which fetches up to 50 URLs on your own host and reports status, redirect chain, canonical, robots directives, title and cache headers, and can test the case, slash and www variants of a URL. It only calls your own server, so it is free.

Does mysite.com serve the same page at different capitalisations?

triage_404s handles the dead URLs: it takes the crawl's 404 and 410 list, verifies up to 50 of them live, sorts them into redirect, review and ignore, and ends with a paste-ready 301 map.

Triage the 404s on mysite.com

On houtini.com it found 256 dead URLs, probed 49 of them live and sorted the lot into 3 to redirect, 46 to review and 207 to ignore; most of them belong to a retired section that answers 410 on purpose.

Then, after the next crawl, ask what moved.

Detect changes on mysite.com

detect_changes diffs the two most recent crawls per URL and classifies each change by severity: a page going from 200 to 404, or a noindex appearing, is critical; a canonical flip is high; a title change is medium. It needs two crawls, so it starts earning its keep from your second refresh.

Tools beyond the crawl

These tools reach past what the crawl can see, starting with field data.

Pull CrUX field data for mysite.com

sync_crux pulls real-user Core Web Vitals from the Chrome UX Report API: LCP, INP and CLS at the 75th percentile, with the good, needs-improvement and poor shares, for your origin plus the top 50 URLs by Search Console clicks, on phone and on desktop. A target's first pull backfills about 25 weekly windows, and later pulls add the newest one, so you get a trend rather than a single reading. The thresholds the dashboard applies are LCP 2.5 s, INP 200 ms and CLS 0.1. It is free and needs only the CrUX key you added during set-up.

The next one shows what JavaScript changes.

Render the top pages on mysite.com and show what only appears after JavaScript

render_pages renders a sample of pages in headless Chromium and diffs the rendered DOM against the raw HTML, which is how you find a canonical, a title or a noindex that JavaScript changes after the fact, and content that only exists once scripts have run. It is opt-in and needs Playwright installed (npm i playwright && npx playwright install chromium).

Then there are near-duplicate pages.

Find near-duplicate pages on mysite.com

find_duplicates embeds the first 200 or so words of each page with a local sentence-embedding model (a 25 MB one-time download) and pairs pages whose cosine similarity is 0.9 or higher. Nothing leaves your machine for this.

Agent readiness is how well AI agents can find, read and use your site.

Check agent readiness for mysite.com

check_agent_readiness probes your origin live and scores four groups. Discoverability covers robots rules, the sitemap and Link headers; content covers llms.txt, agents.md and Markdown negotiation; bot access control covers AI-bot rules, Content Signals and Web Bot Auth; and capabilities covers an MCP server card, Agent Skills, an API catalogue and OAuth discovery. It needs no crawl and no Search Console data, and it returns a 0-100 score, a level and copy-paste fixes. houtini.com scored 23 of 100, which the tool calls "Some agent signals": it has robots.txt, a sitemap and OAuth discovery, and it has no llms.txt, no AI-bot rules and nothing else in the capabilities group. The llms.txt fix, for example, reads: "Add /llms.txt - a plain-text reading list pointing agents at your most useful pages/docs."

score_passages uses a small local model, a cross-encoder that downloads once, to score whether one passage on each page answers that page's top query, at about 0.6 seconds a page, and the result feeds the weak-passage-answer check.

The Crawl health tab on the Larchmere demo site: 290 pages crawled, 237 indexable, the status mix, a canonical, redirect and not-found breakdown, and response codes, indexability, response times and crawl depth

Crawl health on the Larchmere demo site: the status mix, redirects and not-found pages, response times and crawl depth.

Content research from your own data

Content research starts with data you already have.

Content opportunities for mysite.com

content_opportunities is composed entirely from stored Search Console data, with no paid calls, and comes back in four groups: write next (demand you earn impressions for with no winning page), refresh now (pages bleeding clicks), rewrite snippets (page-one rankings that are under-clicked) and strengthen (clusters sitting at positions 4 to 20). On houtini.com, refresh now put the LM Studio set-up guide first, down from 59 clicks to 21; rewrite snippets led with the query "houtini" at position 2.7 and a 2% CTR against 11% expected; strengthen put the "dgx spark alternative" cluster first, 52 keywords and 14,047 impressions; and write next was "best local ai server", 686 impressions with a best position of 46.

Two more free tools sit beside it. suggest_pages proposes new pages from queries that earn impressions at rank 11 or worse with no winning page, one page per intent, each with the nearest existing page to link from. keyword_list clusters your top 500 Search Console queries by the page Google already ranks for them and gives a verdict per cluster: own, weak or absent. When you have picked a row from any of those lists, ask for the brief.

draft the brief for row 1

draft_content returns a grounded writing brief: the query gap, the page's own paragraphs as voice exemplars, and the most query-relevant passages as the only permitted facts. There is no bundled LLM; the writing is yours or Claude's, from that brief.

The paid layer, when you want it, is DataForSEO. keyword_volume gives monthly volume, CPC and competition for up to 700 keywords in a call. search_intent classifies up to 1,000 keywords a call as informational, navigational, commercial or transactional, with probabilities. related_terms returns People Also Ask and related searches, one SERP call per keyword, so use it on the terms you have chosen rather than a list. topic_trend reads Google Trends for up to five keywords and says rising, falling or flat. news_discovery reads Google News free, with no key, and adds DataForSEO's richer news SERP when credentials are set; youtube_discovery lists the videos ranking for a term.

For the topics your competitors cover and you don't, use topic_gaps.

What topics should mysite.com cover? Compare against rival.com

It takes up to three named competitors' footprints, subtracts every query your Search Console already shows and the topics you cover, clusters what is left and ranks it by volume times competitor coverage, in at most four cached calls.

Content recon is the step after that, for the pages you already rank with.

Run content recon on mysite.com

recon_targets takes your striking-distance pages, the ones whose top query sits at positions 3 to 15, highest impressions first. It fetches each live page, pulls the live Google SERP and sorts each page into one of five verdicts on organic rank against AI Overview citation: defend and deepen, accuracy or freshness, consolidate a weak page, competitive gap, or page cannot rank. It costs about $0.004 a page, so a ten-page recon is a few cents. The gaps it finds go to a to-do board with save_recon_todo and recon_todos, which tracks each one from open to shipped and can re-measure the SERP after you ship.

The Opportunities tab's content architecture panel on the Larchmere demo site: topic clusters such as walking boots and best waterproof jacket, each with the share of its demand already covered and internal-link suggestions

Topic clusters on the fictional Larchmere demo site, each with the share of its search demand the site already wins.

The Opportunities tab on the Larchmere demo site: the biggest quick wins ranked by recoverable clicks, led by walking boots with 774

Opportunities on the Larchmere demo site, led by the query "walking boots" with 774 clicks recoverable.

The Content research tab on the Larchmere demo site, with a keyword box for waterproof jackets and News, Videos and Trend buttons above a list of news articles

The Content research tab on the Larchmere demo site, where news, video and trend lookups run from one keyword box (the rows are demo fixtures).

Top pages and competitors

These tools all run on DataForSEO Labs, so they work on any domain, yours or not, and need no Search Console access.

Top pages on competitor.com

top_pages lists a domain's top organic pages by ETV (estimated traffic volume) with the keyword count behind each. Run on houtini.com, it put the Claude in Excel article first, ETV 120.37 from 17 keywords, and the call cost $0.0132.

Show visibility over time for competitor.com

domain_visibility is the trend view: monthly organic visibility for any domain, twelve months by default and up to 24.

Find competitors for mysite.com in the UK

competitors_domain ranks the domains that overlap your keyword set.

Content gap between rival.com/guide and my /guide page

page_intersection is the page-level content gap: what a rival's URL ranks for that your page doesn't, with up to 20 competitor URLs and wildcards.

What does competitor.com/blog/ rank for?

ranked_keywords takes a domain, a subdomain, a folder or one URL and returns the keywords it ranks for in one call. With aioOnly it narrows to the keywords where you rank and the SERP shows an AI Overview. That is exposure, not citation; whether Google cites you is what content recon checks.

Which of mysite.com's keywords show an AI Overview?

serp_features is one cached call over your keyword universe, volume-weighted: what share carries an AI Overview, a featured snippet, People Also Ask, shopping or video. market_sizing takes your domain plus up to four named competitors and returns total demand, share of voice overall and per topic cluster, and the leader in each.

Size the market: mysite.com vs rival1.com and rival2.com

For houtini.com we ran a competitor keyword gap, with competitors_domain for the overlap, ranked_keywords on the rival domains, topic_gaps, and keyword_volume for US and UK demand, and we scored what came back on demand, fit and winnability. Two rival groups came out of it, explainer sites and niche local-AI sites, and the rivals won with five content types: comparisons, pricing and limits pages, per-feature how-tos, benchmark-backed "best X" pages and calculators. Seven of the 25 opportunities turned out to be updates to pages we already had. For a hardware review and affiliate site of around 370 pages we ran a true-gap analysis against two peers and the big publishers, using domain_visibility, competitors_domain, ranked_keywords, and page_intersection on the rivals' URL patterns. That gave us a pool of about 1,300 true-gap keywords grouped by cluster, and it removed about 50 false gaps, which were keywords the site already ranked for in Search Console. It also showed one page ranking for a huge head term at position 8.5 with a single click.

Internal links come first, because they cost nothing to analyse. The crawl stores every internal link with its source, target, anchor and placement (body, footer or navigation) in the links table, and query_data reads it.

Which of my pages aren't indexed, and how much internal link equity does each one get? Separate the underlinked from the true anomalies.

For an orphaned page that earns impressions, fix_finding suggests an anchor and the pages to link from, as a dry run. The Network tab draws the same graph: node size is internal PageRank, colour is health, with equity against traffic by template, a folder-to-folder Sankey, and a Trapped authority report once backlinks are in.

The Network tab on the Larchmere demo site: internal link equity against organic traffic by page template, and a Sankey chart of link equity moving between site folders

Link equity on the Larchmere demo site's Network tab: product pages hold most of the internal link equity, while the guides and the homepage earn more of the traffic.

External links need DataForSEO's Backlinks API, which is switched on for your account separately from the Labs and SERP families, and the tool tells you if it isn't on yet.

Pull the backlinks for mysite.com

pull_backlinks brings in the backlink profile, the live HTTP status of every backlinked page (which feeds the backlinks-to-404 check), referring domains, anchors classified as branded, keyword, URL, generic or empty, and a month-by-month history of new and lost referring domains.

What links does rival.com have that we don't?

link_intersect returns the domains that link to your rivals but not to you, across up to 20 competitors, filters them by spam score and saves them as a prospect list, all in one cached call at about $0.024. With a Majestic key the top prospects are enriched with Trust Flow and Topical Trust Flow, and the list re-sorts by Trust Flow. Trust Flow is Majestic's 0-100 measure of editorial authority, propagated from a seed set of trusted sites, and Topical Trust Flow says what that authority is about. Nothing is filtered out on the Majestic numbers; they set the order of the list.

For a backlink check and link-gap prospecting we ran pull_backlinks per URL, then link_intersect across 13 peer domains. One run produced 230 prospect rows, we rejected about 117 link-gap domains as spam or link farms, and the 39 pairwise intersections cost about $1.10. On a hardware affiliate site we ran an equity rescue with the backlinks-to-404 and traffic-to-dead-url checks, which found three backlinked URLs returning 404 (up to about six backlinks each) and unpublished pages with past impressions and no redirect. To map hubs and spokes on a site with about 96,000 crawled links, we read the topic links out of the crawl's links table, which gave us 33 hubs and 303 topic links. It also flagged hubs with many spokes but near-zero clicks, and high-impression pages with only one in-content link.

The Links tab on the Larchmere demo site: 4,120 backlinks, 386 referring domains, Domain Rank 212, 91 broken backlinks, a new versus lost referring domains chart and a table of top referring domains

The Links tab on the Larchmere demo site, the view that pull_backlinks fills.

Rank tracking and the portfolio

Track ranks for mysite.com in the UK

track_ranks pulls DataForSEO's monthly rank distribution and ETV for a domain into the rank_history table, with history back to October 2020, cached 20 days. That feeds the search-visibility-over-time chart, which isn't limited to the 16 months the Search Console charts hold.

The portfolio is new in 0.17.0, released on 25 October 2026. It is one table across your owned properties and the domains you watch, such as competitors, prospects or clients whose Search Console you don't have, with a per-domain overview behind each row. The columns are clicks over 28 days (measured, owned sites only), organic keywords and estimated traffic, referring domains, Domain Rank (DataForSEO's authority score), AI mentions across Google AI Overviews and ChatGPT, and audit health. A "needs attention" flag follows fixed rules: Search Console clicks down 20% or more from at least 200, estimated traffic down 30% in a month or 20% two months running, referring domains down 10% from at least 50, Domain Rank down five points, AI mentions down 30% from at least 20, audit health down five points, or stale data.

Add rival.com to my portfolio as a competitor in the UK
Refresh my SEO Console portfolio

A refresh quotes first and spends nothing until you confirm, and the actual spend is recorded. In a live run on 24 October 2026, eight domains on the weekly tier cost $0.22. You can schedule it: a weekly tier on a weekday and a monthly tier on a day of the month, under a monthly budget cap in dollars, and a run that would breach the cap stops and says so.

The dashboard

Most of what's above also shows up in a dashboard, in eight tabs: Summary, Issues & fixes, Crawl health, Network, Search performance, Opportunities, Links and Content research. The Summary is the one to open first. It carries a freshness line per source, a one-sentence templated verdict, six tiles (organic clicks over 28 days against the prior 28, non-brand share, site health, indexed pages, field Core Web Vitals, AI readiness), clicks by month, what's broken by area, a "Do this first" list of five fixes, and what changed since the last crawl. Nothing on it is estimated or written by a model.

Open the dashboard for mysite.com
Export the report for mysite.com

get_dashboard shows it in chat; serve_dashboard runs the same thing on a localhost-only web server with a property switcher and CSV downloads; open_dashboard starts that server if needed and hands you the link; export_report writes one self-contained HTML file to the reports folder as a snapshot. For sharing a screen without sharing the numbers, add &redact=1 to the link and it blurs the property name, the traffic figures, the URLs and the network labels.

The Search performance tab on the Larchmere demo site: clicks, impressions, CTR and average position tiles, 90 days of daily clicks, impressions and position, top keywords and pages, and the branded versus non-branded split

Search performance on the Larchmere demo site: 59% of the clicks are non-branded.

What we've used it for

I use it on the daily, I use it to measure and monitor the performance of all of my own properties. Here are five jobs we have done with it, on houtini.com or on other sites anonymised to their type.

Diagnosing a traffic fall

A small site had a sudden traffic fall, so we re-synced Search Console from a fixed date, ran query_data at daily grain, week on week by page, and ran inspect_urls on the top 25 pages. About half of a "minus 50% week" turned out to be a surge week unwinding. The other half was real: head terms were down three to five positions, and the sitelink rows that jump to a page's sections were down about 80%.

A health check on an affiliate site

On a hardware review and affiliate site of around 370 pages, the health check was an incremental sync_gsc, a fresh crawl of 631 URLs in about three minutes, then run_audit, which returned 1,264 findings, 4 of them critical. The biggest find was pages returning 404 that still earned clicks, about 800 a quarter. Behind that came 149 pages with CTR far below the position-expected rate, 40 pages that had decayed over 28 days against the prior 28, and four hubs whose JSON-LD would not parse.

Query ownership

On the same site we worked out which page owns which query, using query_data by query and anchor across pages, the keyword-cannibalisation check and DataForSEO volumes for each query family. One page took about 98% of impressions on one query family while a sibling took about 1%. We went through the 40 pairs the check flagged and kept most of them as deliberate; a few were real splits, two reviews sharing one product query among them.

AI Overview exposure

For houtini.com, one cached serp_features call over 175 keywords showed People Also Ask on about 92% of sampled volume, video on about 71% and an AI Overview on about 67%. We were on page one for only two of those AI Overview keywords.

Pages that earn no search traffic

To sort the houtini.com pages that earn no search traffic into unpublish, merge, keep and improve, we ran query_data for the top 25 queries on every page with ten or more impressions and pull_backlinks per URL, and joined both to a crawl for inlinks and dates. Four pages carried about 86% of clicks over three months. Only about 15% of sitemap URLs had even a single click, and about 38% had no Search Console rows at all. We held pages under about nine weeks old out of the sort.

If I still ran an SEO agency, this is the work I'd be doing in house to make things more efficient. If I was an in-house SEO, I'd be doing much the same, so I could challenge my agency to deliver what can't be done in house.

Where to start

Install with npx, add the service account's email to the property, then type these three prompts in order.

Refresh sc-domain:yoursite.com
Run an SEO audit on yoursite.com
Generate the fix for #1

Ship the fix at the top of the list this week, then refresh and run the audit again. On houtini.com the crawl's fetch stage took 142 seconds and the audit 315 milliseconds.

Continue reading.