Audit localhost, not just what you already shipped.
A hosted scanner cannot open http://localhost:3000 - there is nothing on the public internet for it to connect to. The LintPage CLI runs on your own machine, so it can. This is the actual command, run against a real dev server on lintpage@0.5.0, output included.
$ npx lintpage localhost:3000
Auditing http://localhost:3000...
... findings ...
READY TO SHIP - 3 warnings - 3 info
localhost mode (localhost): 16 checks not run (they need a public origin), 4 downgraded to info.
$ echo $?
0no config - no account - runs against http://localhost:3000 by default
It is not a missing feature. It is a missing route.
Paste a URL into any hosted audit tool, browser extension, or Slack bot and it does the same thing under the hood: a server somewhere else on the internet opens an outbound connection to your URL and reads what comes back. That works for https://your-app.com because it has a public address a stranger's server can route to.
http://localhost:3000 does not have one. Loopback addresses only resolve on the machine that opened them - that is what makes them loopback addresses. A hosted crawler asking the internet to route it to your laptop gets nowhere, the same way a letter addressed to "the kitchen" with no street address gets nowhere. This is not a rule anyone chose to enforce. It is how private networking has worked the whole time.
The LintPage CLI does not have that problem, because it never leaves your machine to look at your machine. It runs as a process on the same host as your dev server and requests the page directly, the same way your own browser tab does. That is the entire trick, and it is the same reason a fixed set of checks cannot run: anything that needs an outside vantage point - fetching your robots.txt as a bot would, checking whether an external service can reach you, crawling your site the way a search engine does - has no outside vantage point to use here. The disclosure below is that same fact, applied check by check.
44 checks run locally. 16 need a public origin.
LintPage runs 60 checks total. Against a loopback target, these two lists are the entire difference from a production audit - generated from the same arrays the CLI itself uses to decide what to run, so this page cannot drift from what the tool does.
Do not run on localhost
16 checks that need a public origin, listed by id.
ai/all-crawlers-blockedai/applebot-extended-disallowedai/chatgpt-user-blockedai/claude-user-blockedai/claudebot-silent-blockai/empty-content-to-botai/google-extended-disallowedai/gptbot-silent-blockai/llms-txt-missingai/perplexity-user-blockedai/perplexitybot-silent-blockbroken-internal-linkscors-policyrobots-txt-checksitemap-presencettfb-pro
Run, but reported as INFO
4 checks whose production assumptions do not hold on a dev server, so a fail there would be noise, not signal. One of them is the response-time finding the runner produces from its own fetch rather than from a rule, which is why the separate rule that measures the same thing appears in the other list rather than this one.
canonical-self-referencinghttps-linkssslttfb
The default text output and --quiet report these as counts, the way the transcript above does. Run with --format json or --format github to get the ids themselves in the output.
Check your share preview before anyone else can.
Facebook's Sharing Debugger and Twitter's Card Validator have the same problem as any other hosted tool: they fetch your URL from their own servers, which cannot reach localhost. In practice that means most teams find out their Open Graph tags are wrong only after a redesign ships and the first Slack link unfurls with a broken image or last quarter's title.
LintPage's Open Graph and Twitter Card checks read the page the same way its other checks do - directly, from the document your dev server just rendered - which is why they are not on either list above. They run on localhost exactly as they run in production, so you can catch a missing og:image, a stale title, or a broken card type while you still have the component open in your editor, instead of after a teammate pastes the link somewhere.
Catch it before it leaves your machine.
Both of these run against the same dev server, before a commit or a deploy exists for a hosted tool to eventually reach.
Pre-commit hook
Run it quiet, against your already-running dev server, and block the commit on a critical finding.
npx lintpage localhost:3000 --quietGitHub Actions
Start the app, then audit the port it is listening on, with annotations for whichever findings turn up.
npx lintpage localhost:3000 --format githubFlag order does not matter. lintpage localhost:3000 --fail-on-warning and lintpage --fail-on-warning localhost:3000 parse identically, as does any other flag in either position.
Local now, full coverage the moment it is public.
next dev serves on localhost:3000 by default, so the command at the top of this page works unmodified against a fresh Next.js app. Run it while you work and you get the 44 checks that do not depend on a public address - meta tags, structured data, headings, Open Graph, accessibility, and more - without waiting for a build, a deploy, or a review.
The moment you open a pull request, Vercel builds a preview deployment with its own public URL. That URL is not a loopback address, so none of the mechanism above applies to it: point LintPage at the preview URL and all 60 checks run, including the 16 that localhost cannot reach and the 3 that localhost reports as informational. Run npx lintpage your-preview-url.vercel.app once the preview is up, the same way you would a production URL with the free page audit.
Questions, answered.
Do I need a flag to audit localhost? +
Why do only some checks run against my dev server? +
Does an audit of a healthy dev server still exit 0? +
Where do I see which specific checks were skipped? +
Can I run --ai-only against localhost? +
Does flag order matter? +
Audit localhost now. Audit the preview URL later.
npx lintpage localhost:3000 today. The free page audit for everything else.
want the full check registry first? see all 60 checks