Krawlify SEO Crawler & Audit
SEO crawler & audit platform

Crawl the sites that block crawlers.

Krawlify is a self-hosted SEO crawler that drives the Chrome you are already signed in to — real profile, real cookies, real sessions — over the standard DevTools Protocol. Four pieces, all MIT licensed, all running on your own machine.

  • No account, no sign-up
  • No pricing tiers
  • MIT licensed
  • Your data never leaves your infrastructure
docker compose up --build
Diagram: your crawler speaks CDP over WebSocket with a Bearer token to a Krawlify relay on port 9333. The Krawlify browser extension dials out to that same relay from inside your Chrome, then attaches the debugger to tabs it opened itself in your real, signed-in profile.
Your crawler connects in; the extension dials out. The relay matches the two by the token in the request — which is why one relay can serve many browsers without holding any of them.
Why this exists

Headless Chrome gave the game away

Every workaround for bot protection eventually runs into the same wall: the browser doing the crawling isn't the browser you actually use.

Bot checks win

A headless browser announces itself a dozen ways. Patch one and the next check catches you, and the fingerprint you spent a week faking is stale by the following release.

Exported cookies rot

Copying a session out of your browser keeps a scraper alive until the session rotates, the IP changes, or the TLS fingerprint stops matching. Then you export them again.

A debugging port exposes everything

Relaunching Chrome with --remote-debugging-port hands your whole profile to whatever connects — every tab, including the ones that have nothing to do with the crawl.

How it works

Krawlify inverts it: your crawler drives this browser

There is nothing to imitate, because the profile doing the crawling is the one already signed in. And there is no forked client to adopt — the relay presents an ordinary DevTools endpoint.

  1. Your code Puppeteer, Playwright, the Krawlify app, or anything that speaks CDP. Unchanged.
  2. Your relay One small container. Many browsers, isolated from each other — the Bearer token picks yours.
  3. The extension Dials out from inside Chrome, opens its own tabs, attaches the debugger to only those.
  4. Your real profile Real sessions, real cookies, the same IP and TLS fingerprint you browse with.
Diagram of a browser tab strip. Two tabs you opened sit outside a dashed Krawlify tab group; two tabs the crawler opened sit inside it. The crawler can address its own tabs, their DOM, network traffic and screenshots, and optionally cookies — but not your tabs' addresses, titles or contents, nor history, bookmarks, downloads, saved passwords, chrome:// pages, other extensions or the Web Store.
A tab becomes visible to your automation only by being created by that automation, and stops being visible when it closes. Chrome does show its “started debugging this browser” banner while the extension is attached — that is Chrome's, and it cannot be suppressed.
Three steps: install the extension in Chrome 125 or newer; on its options page set the relay URL and copy the token the browser generates; paste that endpoint and token into a crawl and run it.
Three steps to get going. After that it is just your crawler again.
Four components

One system, four pieces you can adopt separately

Use the app on its own. Add the extension and relay when a site fights back. Add the agent skill when you would rather ask for the audit than run it.

Krawlify app

Self-hosted platform

A multi-user website crawler with Screaming Frog–style data tabs, live progress streaming, a REST API, and an MCP server so an AI assistant can run audits itself.

  • 13 result tabs — Internal, External, Response Codes, Page Titles, Meta Description, Headings (H1–H6), Directives, Images, Broken Assets, Links, Redirects, Sitemaps (orphan pages) and Dates.
  • Live progress over SSE — the dashboard updates as pages land, without polling.
  • Reads the site properly — robots.txt, sitemaps including nested <sitemapindex>, redirect chains, and status checks on external links and assets.
  • Dates from JSON-LDdatePublished and dateModified from schema.org markup, matched against sitemap <lastmod> per URL.
  • Multi-user — member and admin roles, per-user crawls and API keys, and guards that stop you disabling the last active admin.
  • Reproducible crawls — every setting is stored on the crawl itself, never read from the environment, so Redo crawl reruns it with exactly what it ran with the first time.
  • Fails loudly, not quietly — if the remote browser drops mid-crawl the run fails with an explanation instead of finishing with a silent hole in the results.
  • Export anything — CSV or Excel per tab with your filters applied, plus a multi-sheet master workbook. Webhooks fire crawl.completed on finish.
# Pull the published image instead of building
docker pull kamenarov/krawlify-app:0.1.0

# Postgres, Redis, migrations, web and worker
IMAGE=kamenarov/krawlify-app:0.1.0 docker compose up -d
# → http://localhost:3000 — register, then start a crawl
Pipeline diagram: a seed URL with depth, limit and politeness settings feeds robots.txt and sitemap parsing, then fetching or rendering, then auditing of titles, meta, headings and images — landing in 13 result tabs that export as CSV, Excel, or read over the REST API and MCP server.
Crawl controls include depth, URL cap, concurrency, politeness delay, request timeout, custom user agent and an optional proxy.

Krawlify browser extension

Chrome 125+ · MV3

Lets your scraping app drive this browser over the DevTools Protocol — in tabs it opens itself, never the ones you have open.

  • Its own tabs only. They are grouped under a purple 🕷 Krawlify label, and the debugger attaches to nothing else.
  • Cleans up after itself. The crawler's tabs close five seconds after the last client disconnects.
  • Three values stored, total — the relay URL, a 256-bit token this browser generated, and whether you last pressed Connect or Disconnect. Nothing in chrome.storage.sync.
  • No telemetry, no analytics, no content scripts. The only connection it makes is to the relay address in its settings.
  • Cookies are opt-in — an optional permission you grant on the options page and can revoke at any time.

Permissions: debugger, tabs, tabGroups, storage, alarms. Optional: cookies, <all_urls>.

The extension and the relay ship from one repository — they are two halves of the same thing.

On the Chrome Web Store. One click, updates handled by Chrome, no developer-mode prompt on every launch. For machines you administer there is still a signed CRX you host yourself and install by policy — and the source is there if you would rather not trust anyone's signature on something that attaches a debugger to your browser.

View the Web Store listing · all three routes, compared

# ExtensionInstallForcelist — force-install from the Web Store
oonpeiliblmkimphjhhfaghpjbjmogon;https://clients2.google.com/service/update2/crx

Krawlify relay

krawlify-relay · port 9333

A switchboard between your crawler and your browser. One Node process, one dependency, loopback-bound by default.

  • Multi-tenant by token. One relay serves many browsers; the Bearer token in the header is what picks yours. The relay has no token of its own and keeps no list.
  • Holds nothing. Tab ownership lives in memory and is discarded when the connection ends. No crawled page content is written to disk.
  • Loopback by default127.0.0.1 unless you opt out, with --tls-cert, --trust-proxy, --allow-host and --allow-origin for anything wider.
  • Ordinary DevTools endpoints/json/version, /json/list, /json/new, /status, /healthz, plus the browser and page WebSockets.
  • Deliberately boring failures. No token and an unknown token look the same from outside.
Relay response codes
CodeMeaning
401No Authorization: Bearer header
503Valid-looking token, but no live browser behind it
404Wrong tenant GUID
421Unexpected Host
403Unexpected Origin
# published image, amd64 + arm64
docker run -p 127.0.0.1:9333:9333 \
  kamenarov/krawlify-relay:0.1.0

# or from a clone
npm start                # → 127.0.0.1:9333

# liveness, unauthenticated
curl http://127.0.0.1:9333/healthz
# control channel: ws /control
status · tabs.list · tabs.create · tabs.close
tabs.activate · tabs.navigate · cookies.get*

# * requires --allow-cookies

Krawlify Agent

Claude Code skill + CLI

Hand an assistant a list of URLs and get back one Excel workbook. A Claude Code agent skill with a CLI underneath — no server, no database, no build step.

  • Only the URLs you give it. No discovery, no link following, no sitemap parsing — which is exactly what you want when auditing a named set of pages.
  • Two ways to get a browser. Relay mode crawls inside the Chrome you already have open, in the 🕷 Krawlify tab group. Launch mode (--launch) starts your installed Chrome on your own profile instead — no extension, no relay, nothing to set up.
  • Faces the bot check in a visible tab for up to 60 seconds, then crawls with the session that cleared it. --wait-full holds it open for captchas and logins you solve by hand.
  • One workbook out — a Summary sheet plus internal, response-codes, titles, meta, headings, directives, images, broken-assets, redirects, links, external and dates.
  • Opinionated thresholds — titles 30–60 characters (561 px), meta descriptions 70–160 characters (985 px), alt text at most 100 characters.
  • Fails early and specifically. Three preflight checks — dependencies, browser credentials, URL list — each with its own exit code, and --check runs all three without crawling anything.

When the endpoint cannot hand over its cookie jar, the crawler fetches from inside the crawl tab and says so in the report — the redirects sheet is empty in that mode, and it tells you why rather than leaving a blank sheet to be misread. The app captures redirect chains in full.

# install once, from npm
npm install -g krawlify-agent

# register it as a Claude Code skill
krawlify-agent install-skill            # ~/.claude/skills
krawlify-agent install-skill --project  # ./.claude/skills

# no relay, no extension — just your Chrome
npx krawlify-agent --urls urls.txt --launch

# check the setup without crawling
krawlify-agent --check
# .env.local — relay mode only
KRAWLIFY_TOKEN=<the token from the extension>
KRAWLIFY_RELAY=http://127.0.0.1:9333

Output lands in your working directory as krawlify-report-<host>-<YYYYMMDD-HHmm>.xlsx.

Live demo

Click around before you install anything

A running Krawlify at app.krawlify.com, seeded and signed-in-ready. Start a crawl, watch the results stream in, page through the thirteen tabs, export a workbook.

  • The real application, not a video or a click-through prototype — the same image you get from docker pull.
  • Try the whole flow — start a crawl, watch Server-Sent Events land, filter and sort a tab, export CSV or Excel, mint an API key and hit /playground.
  • Bot-protected sites need the browser path, which means your own Chrome and your own token — that part cannot be demonstrated on someone else's server. See the quickstart.

It is a shared, public sandbox. Treat everything in it as public. The account below is an administrator, and everyone signing in gets the same one — so anyone can see, change or delete anyone else's crawls, keys and settings.

Do not crawl anything confidential, do not paste a real API key, a real proxy password or a token from your own extension into it, and expect the whole instance to be reset without notice.

Open the demo

Sign in with

Email [email protected]
Password demo1234
URL https://app.krawlify.com

These are the credentials the project's own prisma:seed script creates. Running the seed on your own install gives you the same pair — change the password on anything reachable from outside your machine.

Quickstart

Running in a few minutes

Start with the app alone. Add the browser path only when a site actually blocks you.

  1. Bring the stack up

    Postgres, Redis, migrations, the Next.js app and the crawl worker, in one command.

    docker compose up --build
  2. Open it and register

    Visit http://localhost:3000 and create the first account. Or seed a demo user instead:

    docker compose run --rm worker npm run prisma:seed
  3. Start a crawl

    Paste a seed URL. Defaults are depth 10, 10,000 URLs, concurrency 8, a 15-second request timeout, and robots.txt respected. Results stream in as pages land.

Three ways in

A UI for you, an API for your code, MCP for your assistant

The same crawls and the same results, reachable three ways. API keys are created in Settings and shown once.

Web UI

Thirteen tabs with server-side pagination, filter presets, sorting and URL search. Light, system or dark, applied before first paint.

REST API

Key-authenticated with Authorization: Bearer or X-API-Key. In-app docs at /docs/api, and a request runner at /playground that renders the equivalent curl.

POST   /api/v1/crawls
GET    /api/v1/crawls/:id
GET    /api/v1/crawls/:id/results?tab=
DELETE /api/v1/crawls/:id

MCP server

Streamable HTTP at /api/mcp, stateless, same API keys. Seven tools: list_crawls, get_crawl, get_crawl_results, list_result_tabs, start_crawl, stop_crawl, delete_crawl.

claude mcp add --transport http krawlify \
  http://localhost:3000/api/mcp \
  --header "Authorization: Bearer YOUR_KEY"
Honest limits

What it does not do

Driving a real browser through an extension buys a great deal, and costs a few things. All of them are worth knowing before you build on it.

One debugger per tab

Opening DevTools on a tab the crawler owns detaches Krawlify from it. Chrome allows a single debugger client per tab, and DevTools wins.

No browser contexts or incognito

Target.createBrowserContext is not supported, so browser.newContext() and incognito windows are unavailable. The point is to use one real profile, so this is a consequence rather than an oversight.

Downloads are not intercepted

Browser.setDownloadBehavior is accepted and then ignored, which means Playwright's download API will not work through the relay.

Some pages can never be driven

chrome:// pages, other extensions and the Chrome Web Store are outside what an extension may attach to. That is Chrome's boundary, not a setting.

Chrome shows a debugging banner

While the extension is attached, Chrome displays its “started debugging this browser” notification. It cannot be suppressed, and anything claiming otherwise is doing something you should not want.

The hosted relay is alpha, and means it

alpha.krawlify.com is the address the extension ships pointed at, so there is a working default rather than a blank field. It carries no uptime commitment, may change without notice, and may be withdrawn. Running your own is one container, and it keeps your crawl traffic off anyone else's machine.

Source & packages

Everything, where you'd expect it

Three repositories, two container images, one npm package and one Web Store listing. All MIT licensed, all published from tagged releases by CI rather than from someone's laptop.

npm

Krawlify Agent
npmjs.com/package/krawlify-agent

Published with --provenance, so npm can attest which repository and workflow built the tarball. The relay is not on npm — it is distributed as a container.

# the crawler and the relay, pinned
docker pull kamenarov/krawlify-app:0.1.0
docker pull kamenarov/krawlify-relay:0.1.0

# the agent skill
npm install -g krawlify-agent

Tags. :edge follows main and moves without warning — useful for trying something, wrong for anything you depend on. A v* git tag publishes the full semver set (0.1.0, 0.1, 0) and moves :latest. Pin the exact version in anything you deploy.

FAQ

Questions people actually ask

Is Krawlify free?

Yes. Krawlify is MIT-licensed software you run yourself. There are no plans, no tiers and no billing — the app, the relay and the agent skill are all free, and there is no account to create.

Is the extension on the Chrome Web Store?

Yes — it is listed as Krawlify under Developer Tools, and that is the easiest way to install it. Two other routes stay supported: a signed CRX you host and force-install by enterprise policy, and a ZIP loaded unpacked. The self-hosted package is signed with a different key, so it has a different extension ID from the Web Store copy; install one or the other, not both.

Can the crawler see my other tabs?

No. The extension attaches Chrome's debugger only to tabs the automation opened itself, and groups them under a labelled tab group. Your own tabs are not filtered out of a list — they are not addressable in the protocol at all, so there is no request the crawler can make that reaches them.

Why is there a relay at all?

A Manifest V3 extension cannot listen on a port, so it can only dial out. The relay is the fixed address both sides can reach: your crawler connects in, your browser connects out, and the relay matches them by the token in the request.

Why does it need a browser extension?

The chrome.debugger API is the only way to speak the DevTools Protocol to a normal Chrome that was not started with --remote-debugging-port. Without the extension you would have to relaunch your browser with a debugging port open, which exposes the entire profile — every tab, not just the crawler's.

Does it work on sites behind Cloudflare?

Often, yes — because the page is fetched by a real Chrome with a real profile rather than a headless one. Krawlify can wait up to 60 seconds for an interstitial bot check to clear, then continue through the same cookie jar, IP and TLS fingerprint. Nothing is guaranteed, and you should only crawl sites you are permitted to crawl.

Do I have to run the relay myself?

No. The extension ships pointed at the hosted relay, so there is a working default and nothing to set up beyond pasting your token. You will probably want your own anyway: it is a single Node process with one dependency, it ships with a Dockerfile and a compose file, it binds to 127.0.0.1 by default, and running it means no crawl traffic passes through anyone else's machine.

What is alpha.krawlify.com?

It is the hosted relay the extension ships pointed at, so the settings page has a working default instead of a blank field. It is alpha and the name is the warning: best effort, no uptime commitment, and it may change or be withdrawn. It is only a switchboard — it holds no browser state and writes no crawled page content to disk — but if a crawl matters to you, point the extension at a relay you run instead.

Does anything get sent to you?

Nothing, unless you deliberately point the extension at our hosted relay. The extension has no telemetry, no analytics and no crash reporting, and the only connection it makes is to the relay address in its settings. This website loads no third-party resources and sets no cookies.

Do I have to change my Puppeteer or Playwright code?

No. The relay presents an ordinary DevTools endpoint. If your code connects to a headless Chrome today with puppeteer.connect or chromium.connectOverCDP, the same call works against your real profile — you change the endpoint and add a Bearer header.

What does the agent skill add over the app?

The app crawls a whole site and gives you a dashboard. The agent skill takes a list of URLs you already have and returns a single Excel workbook, which is what you want when an assistant is doing the audit for you and needs a file to hand back.

Is there a demo I can try first?

Yes — app.krawlify.com runs the real application, and the sign-in details are published on this page: [email protected] with the password demo1234. It is a shared public sandbox on a single administrator account, so everyone who signs in sees and can change everything. Do not put anything confidential into it, do not paste a real API key or a token from your own extension, and expect it to be reset without notice.

Where is the source, and how do I install it?

Three repositories on GitHub: krawlify-app, krawlify-relay (which holds both the extension and the relay) and krawlify-skill. The app and the relay are published to Docker Hub as kamenarov/krawlify-app and kamenarov/krawlify-relay, built for both amd64 and arm64. The agent skill is on npm as krawlify-agent. Every artefact is published by CI from a tagged release, never from a laptop.

Can I self-host all of it?

Yes, and that is the intended way to run it. The app, the crawl worker, Postgres, Redis and the relay all come up from Docker Compose on your own machine or server. The only component that lives anywhere else is the extension, which lives in your browser.

Start with one command

Bring the stack up, register, and point it at a site. Add the browser path the first time something blocks you.