Everything Bulk URL Checker does with a large list.

Written against what the product does today. Where there is a number on this page it comes from our own database, and where we could not support a claim we removed it rather than soften it.

Getting the list in

Four ways to hand over up to 100,000 URLs.

Whatever shape the list is already in, that is the shape you can give it to us in. Nothing to install and nothing to keep open.

Paste it
One URL a line, straight from a spreadsheet, an export or your clipboard. Duplicates are removed and counted, and anything that is not a URL is dropped and counted rather than silently checked.
Upload a file
CSV or Excel. We find the column with the URLs in it, so the export does not have to be tidied first.
Give us a domain
Point us at a site and we read its own list of pages, then check every one. Useful when nobody has an export and somebody wants an answer.
Send it from code
The REST API, the Python and Node SDKs, or the hosted MCP server so Claude or ChatGPT can run the check. Same backend, same credits, no plan required.

Getting a straight answer

Blocked is not broken, and we go back to prove it.

This is the part you cannot get from a script you wrote yourself. Run a big list from one machine and sites start turning you away; the results fill with refusals you then check by hand.

We come back for the refusals
When a site turns us away, the URL is checked again by an independent route before any verdict is written. Only what is still refusing after that gets reported as refused.
We pace ourselves per site
Requests to one site are spaced so that a big list does not turn into a hammering that gets the whole domain to shut the door.
Five verdicts, one of them broken
Recovered, Gone, Still refusing, Blocked for legal reasons and Working are reported apart. Only Gone counts as a broken link.
Pages that lie about being fine
A page that answers 200 while saying "not found" is a soft 404. We detect those and flag them separately, which a status-code-only checker cannot do.
The whole redirect chain
Every hop and the URL it finally landed on, because a link that moved is not a link that broke.
No confidence scores
When we cannot get a straight answer we say so and name the reason. We do not put a probability on a link and leave you to interpret it.

Measured on our own production database over the 90 days to 21 September 2026, across 603 jobs and 41,308 distinct domains: 56,892 URLs refused at least one request, and 13,597 of them answered when we came back by a different route. That is 23.9% of the refusals, and every one is a link your own run would have handed you as broken.

What comes back

A report you can filter, export and send to a client.

A run of this size takes a few minutes and needs nothing from you while it happens. Close the tab; the email arrives when it is done.

Filter by verdict
Narrow to the dead ones, the ones that moved, or the ones still refusing, and search within the list.
Export what you filtered
CSV or JSON, of the rows you actually want rather than the whole run.
Email when it is ready
You do not sit and watch a progress bar. We write to you when the report exists.
Share a report by link
Send a read-only link to somebody without an account, which is how most people hand results to a client.
Read it from code
Page through the results over the API, with stable cursors so a full export is not disturbed by URLs finishing mid-download.
Results while it runs
Rows appear as they are checked. On a long list you can start working before the run finishes.

Scheduled checks

Re-run any list on a schedule and hear only what changed.

Setting one up costs nothing. Only the runs use credits, and they are included on every plan and during the trial.

Daily, every three days, weekly or monthly
Up to 100,000 links each time, from the same sources as a one-off check.
The difference, not the whole report
Each run is compared with the last one, and the alert is about what moved. Nothing changed means nothing lands in your inbox.
Email, Slack or your own webhook
Everyone you add confirms their address first, so an alert never quietly disappears into a filter nobody owns.
A threshold you set
One link flapping should not wake anybody up. You decide how much has to move before we write.
Recoveries too, if you want them
Knowing a link came back matters when a client asked about it last week.
A calendar of what ran
Every past and upcoming run in one view, with the report from each one a click away.

API · SDKs · MCP

A URL checking API, two SDKs and a hosted MCP server.

Every surface shares one backend and one pool of credits. One credit per URL, wherever the request came from, on every plan.

REST API
Start a job and poll it, or use the single blocking call for small batches. Idempotency keys make retries safe, and every response carries a request id.
Python and Node SDKs
Type-hinted Python with a CLI, and strict TypeScript with both ESM and CJS builds. MIT licensed, both with a webhook signature helper.
Hosted MCP server
Works in Claude, ChatGPT and Cursor with an interactive sign-in, so there is no API key to paste into a config file.
Webhooks
We post a signed event to your endpoint when a job finishes, rather than you polling for it. Signatures verify with a helper in both SDKs.
OpenAPI and Postman
A machine-readable contract and a prebuilt collection, so the first request works before you have written anything.
Rate limits that tell you about themselves
Every response carries what is left and when it resets, so a client can pace itself rather than guess.

Read the developer docs

Try 15,000 URL checks your first month, on us.

No card. Setting up a scheduled check costs nothing; only the runs use credits, and unused credits roll over.

See pricing

We use analytics cookies to improve your experience. Opt out anytime in Cookie Settings. Privacy Policy

Settings