Seat-based SEO pricing has a shape that’s easy to miss until you do the arithmetic. A small site tracking a dozen keywords and pulling one competitor report a month is paying the same monthly figure as an agency running the tool all day — and often paying more for that seat than for the hosting underneath the site it’s measuring.
That’s not a Semrush problem specifically. It’s what happens when a tool is priced for an agency and sold to everyone else. You end up renting a dashboard you mostly don’t use, on someone else’s schedule, with your data living wherever they decide to put it. Fast, polished, and none of it yours.
OpenSEO is a self-hosted, open-source SEO platform: keyword research, rank tracking, backlinks, and site audits, all running against your own DataForSEO API key instead of a subscription. You clone it, deploy it to Docker or Cloudflare, and pay DataForSEO directly for the data you actually pull. There’s also a hosted version at $10/month if you’d rather not run it yourself. The pitch is straightforward: same category of data, none of the seat-based pricing, and you keep the keys.
The honest objection is that SEO tooling is a crowded, mature category, and self-hosting a marketing tool is a strange hill to build a side project on. Most of us use whatever our team already has a licence for, and swapping that out for something you have to deploy and patch yourself is a hard sell unless the alternative buys you something real. What OpenSEO buys you is an MCP server. Point Claude Code, Codex, or Claude Desktop at it and your agent gets live keyword volume, SERP data, and backlink numbers instead of guessing from training data — which is the actual gap self-hosting closes here, not the money.
The part I actually find interesting
The repo doesn’t just claim its audit engine works. It ships proof, as a second app called badseo, a deliberately broken test site where every page violates exactly one SEO rule: a missing <title>, a redirect loop, a page nothing links to, thin content, a 500 that should be a 404. A CI harness then crawls a live copy of badseo with OpenSEO’s real audit code — imported straight from the main app, not mocked — and checks that each page trips the issue it’s supposed to trip, and nothing else.
Each fixture is a typed object, checked against the actual issue registry at compile time:
const myFixture: Fixture = {
path: "/category/my-mistake",
category: "Content quality",
name: "My SEO mistake",
expectedIssues: ["thin-content"], // type-checked against the real audit registry
handler: () => htmlResponse(renderPage({ fixture: myFixture, ... })),
};
I assumed, going in, that “audit tool” meant something like Lighthouse: a scoring model tuned against reference sites and hoped to be accurate. This is a different design. Every rule the audit engine can detect has a corresponding page whose only job is to fail that rule, and the test suite fails if coverage slips. It’s a small idea — write your regression tests as a public, ranking-safe website — but it’s the kind of decision that tells you the crawler was built by people who got burned by false positives before, not people demoing a feature.
Setup, in practice
Docker is the fast path:
cp .env.example .env
# set DATAFORSEO_API_KEY in .env
docker compose up -d
# opens on http://localhost:3001
That mode runs with AUTH_MODE=local_noauth, no login, an injected admin@localhost user. Cloudflare is the option for a team or anything internet-facing, and it’s a heavier lift: Node 22.6+, pnpm alchemy login, then pnpm deploy:selfhost, which provisions D1, KV, R2, and a Cloudflare Access gate in one pass. R2 needs a payment method on file before Cloudflare will even let you enable it, free tier or not.
Once it’s running, wiring up an agent is one line:
claude mcp add --transport http --scope user openseo http://localhost:3001/mcp
From there you get nine SEO-focused Agent Skills — seo-project-setup, seo-audit, keyword-research, keyword-clustering, competitor-analysis, competitive-landscape, local-seo, link-prospecting, seo-coach — installable with npx skills add every-app/open-seo, or one at a time with --skill [skill-name]. The one worth calling out is seo-project-setup: it writes business context, goals, competitors, and key pages into a shared project record that every other skill reads before doing anything, and every skill checks a 30-day research log before spending credits on the same query twice.
Caveats, honestly
The Docker default has no auth. AUTH_MODE=local_noauth is fine on a laptop, but the docs are explicit that you need your own reverse proxy or private network in front of it before exposing it anywhere. Skip that step and your DataForSEO key and project data sit behind nothing.
External PRs aren’t reviewed right now. The maintainer states this plainly in CONTRIBUTING.md: AI-assisted contributions are hard to vet at the current volume, so issues are the contribution path and PRs sit unmerged. That’s a reasonable call for a single-maintainer project, but it means bus factor is effectively one — Ben Senescu, per the README’s X link — and community fixes don’t land on their own timeline.
It’s genuinely early. Version 0.1.7 at the time of writing. The most recent release notes fix SAM (the in-app AI assistant) crashing on tool-heavy answers and SERP lookups failing outright when Google returned no results — not edge cases, core paths.
DataForSEO has its own floor. There’s a free trial to get started, but DataForSEO’s pricing page is explicit that “the minimum payment amount is $50” once you’re past it. Self-hosting removes OpenSEO’s fee, not DataForSEO’s.
Skip it if you need a supported vendor relationship, you’re not comfortable operating a Cloudflare Worker or Docker container as infrastructure, or your team’s SEO workflow is already built around Search Console exports rather than an MCP-connected agent.
Where it sits
| OpenSEO (self-hosted) | Semrush / Ahrefs | |
|---|---|---|
| Best at | Pay-per-use data, direct MCP access for coding agents, full control of where project data lives | Polished UI, mature feature depth, support contracts, non-technical teams |
| Falls down on | No managed support, 0.1.x stability, you own uptime and the DataForSEO relationship | Seat pricing scales badly for light or occasional use |
What I’d steal from this for my own tooling isn’t the SEO logic, it’s the badseo pattern. Any tool that classifies or flags things — a linter, a link checker, an accessibility scanner — could use the same trick: a small, deliberately broken fixture site as a public, versioned proof that detection still works, instead of trusting a green test suite you can’t independently verify.