Bulk Url Checker

io.github.carlosofscience由 GitHub 账号 carlosofscience 发布v1.0.1更新于 Nov 1, 2026

Bulk HTTP status checker: up to 100,000 URLs per job, with redirect chains and response times.

已验证Streamable HTTP可网页运行网页搜索与抓取开发者工具

概览

AI 生成的概览

远程 MCP 服务器,让助手批量提交网址做 HTTP 状态检查,并取回状态码、重定向链和响应时间。

可以做什么
  • 提交网址列表进行检查,小批量直接返回结果,大批量返回任务 ID
  • 查询任务状态与进度,并分页获取结果,含状态码、响应时间和错误信息
  • 列出账户已验证的域名,已验证域名的检查速度明显更快
  • 查询账户当前剩余的检查次数
适用场景
适合批量链接审计、死链检测,以及在大批网址上检查重定向和响应时间;当需要托管代理和按域名限速、不想自己搭建检查器时尤其合适。
运行要求
通过 streamable HTTP 连接 mcp.bulkurlchecker.com 远程端点;清单未声明认证,但服务按账户计费,README 提到 API 密钥与付费配额。如需域名验证,要在网页控制台通过 DNS TXT 记录或 meta 标签完成。
安装前请注意
提交的网址会发送给第三方云服务,并由其通过住宅代理抓取。检查会消耗计量配额,免费额度用完后套餐为每月 9 至 99 美元,另有付费的额度包。README 提到的账户 API 密钥和 webhook 签名密钥应妥善保管。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Bulk Url Checker,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Web executable,通过 Streamable HTTP。 远程服务在工作区中配置后即可从网页运行时运行。

交给智能体安装

把这段提示词粘贴到 Claude Code、Codex、Cursor 等智能体,或 SourceWeft 对话中。智能体会读取该服务器的安装指南,先向你展示发布者、端点和登录方式,经你同意后再把它添加到你的客户端。密钥不会写进任何命令。

阅读 https://sourceweft.com/mcp/io.github.carlosofscience%2Fbulk-url-checker/install.md,并按其中说明把这个 MCP 服务器接入我的客户端。修改任何配置之前,先告诉我它的发布者、端点和登录方式,等我确认。不要把 API 密钥写进命令或我会提交的文件;问我密钥应从哪里获取。

查看智能体所依据的安装指南

其他 MCP 客户端

把它添加到你客户端的 mcpServers 配置中。

{
  "mcpServers": {
    "bulk-url-checker": {
      "type": "http",
      "url": "https://mcp.bulkurlchecker.com/mcp"
    }
  }
}

README

bulkurlchecker

[PyPI version] [Python versions] [License: MIT]

Python client for the Bulk URL Checker API.

Skip the proxy-rotation, rate-limiter, soft-404 detector, and retry classifier you would otherwise spend two weeks building. Submit thousands of URLs, get status codes, redirect chains, and broken-link detection back as plain Python objects. Backed by a managed cloud service with residential proxies and per-domain throttling.

Install

bash
pip install bulkurlchecker

5-line example

python
from bulkurlchecker import Client
client = Client(api_key="uck_live_...")results = client.check_urls(["https://example.com", "https://example.org"])for r in results.results:    print(r.url, r.status_code, "BROKEN" if r.is_broken else "ok")

Get an API key at https://app.bulkurlchecker.com/dashboard/api-keys. First 300 URLs are free, no card required.

What you get back

python
results = client.check_urls(urls)
results.status            # 'completed' | 'paused' | 'failed' | 'cancelled'results.timed_out         # True if the wait deadline passed (job still running)results.total_urls        # how many URLs the engine acceptedresults.completed_urls    # how many it finished checkingresults.duplicates_removedresults.invalid_urls_rejected
for r in results.results:    r.url                # the original URL you submitted    r.final_url          # after redirects    r.status_code        # 200, 301, 404, 429, 500, ...    r.redirect_chain     # list of intermediate URLs    r.is_broken          # True if the engine flagged this as broken    r.is_soft_404        # True if 200 OK but page content says "not found"    r.response_time_ms
# Convenience properties:results.broken           # list of URLResult where is_broken == Trueresults.soft_404s        # list where is_soft_404 == True

Command-line usage

Install with the [cli] extra to get the bulkurlchecker command:

bash
pip install 'bulkurlchecker[cli]'export BULKURLCHECKER_API_KEY=uck_live_...
# One URL per line in urls.txt → CSV on stdoutbulkurlchecker check urls.txt > report.csv
# Pipe from anywheresitemap-extractor mydomain.com | bulkurlchecker check - --output jsonl > report.jsonl
# Only show broken URLs, ad-hoc inputbulkurlchecker check --urls "https://example.com,https://example.org" --only-broken
# Two-step (submit, then poll & fetch later)JOB=$(bulkurlchecker submit urls.txt)bulkurlchecker status "$JOB"bulkurlchecker results "$JOB" --output csv > report.csv

Output formats: csv (default), json, jsonl. Run bulkurlchecker check --help for the full flag list.

Larger jobs: submit and poll

check_urls() blocks for up to 15 minutes server-side. For lists where the wait would time out, use the two-step pattern:

python
job = client.submit(my_500k_urls)print(f"Submitted {job.job_id}, {job.total_urls} URLs queued")
# Poll explicitly, or use the convenience methoddone = client.wait_until_done(job.job_id, timeout=3600)
# Stream results in pagesfor batch in client.iter_results(job.job_id, page_size=1000):    for r in batch:        if r.is_broken:            print(r.url, r.status_code)

Safe retries with idempotency_key

Pass an idempotency key on submit() or check_urls() to make retries safe under network failures. The server caches the response for 24 hours; a retry with the same key + same body returns the original result without creating a duplicate job.

python
import uuid
key = str(uuid.uuid4())  # generate once per logical request
# First call: creates a new job.job = client.submit(urls, idempotency_key=key)
# Network blip, no clean response received? Just retry with the same# key -- you'll get the SAME job summary back, no duplicate submission.same_job = client.submit(urls, idempotency_key=key)# job.job_id == same_job.job_id

Same idempotency_key + different urls returns 409 Conflict (raised as ValidationError) so client bugs that reuse a key against a new payload are caught loudly instead of silently mapping to the wrong cached response.

Receiving webhooks

When a job finishes, we POST to your registered endpoint with a signed payload. Verify the signature before trusting the body — anyone who knows your endpoint URL can otherwise send fake events.

python
from flask import Flask, requestfrom bulkurlchecker import verify_signature, InvalidSignatureError
SECRET = os.environ["MY_WEBHOOK_SECRET"]  # the signing_secret we showed once
app = Flask(__name__)
@app.route("/webhook/bulkurlchecker", methods=["POST"])def webhook():    try:        verify_signature(            request.get_data(),  # RAW bytes — not request.get_json()            request.headers.get("Bulkurlchecker-Signature", ""),            SECRET,        )    except InvalidSignatureError:        return "", 401    event = request.get_json()    if event["type"] == "job.completed":        job_id = event["data"]["job_id"]        # ... fetch results, update your DB, ping Slack, etc ...    return "", 200

Register endpoints + get secrets at https://app.bulkurlchecker.com/dashboard/webhooks (or via POST /api/v2/webhooks/endpoints).

verify_signature() enforces a 5-minute timestamp tolerance by default to defeat replays. Tune via tolerance_seconds=.

Error handling

All errors derive from BulkURLCheckerError. Catch specific subclasses when you want to branch on the failure mode:

python
from bulkurlchecker import (    Client,    BulkURLCheckerError,    AuthenticationError,    RateLimitError,    QuotaError,    ValidationError,)
try:    results = client.check_urls(urls)except QuotaError as e:    print(f"Out of credits. Top up at https://app.bulkurlchecker.com/billing")except RateLimitError as e:    print(f"Rate limited. Retry after {e.retry_after}s.")except AuthenticationError:    print("API key rejected — check it's not revoked.")except ValidationError as e:    print(f"Bad request: {e}")  # bad URLs, too many URLs, etc.except BulkURLCheckerError as e:    print(f"Other error: {e} (request_id={e.request_id})")

Every error carries status_code, code (server's machine-readable string), request_id (for support), and details (when the server provides them).

Why use this instead of writing your own checker with httpx + asyncio?

Honest answer: for ≤500 URLs you don't need this. The standard requests/httpx toolchain handles it fine.

The wall hits at scale:

ProblemRolling your ownThis SDK
Concurrencyasyncio + careful semaphoresdone
Proxy rotation across residential IPs$90+/mo Webshare / Bright Data subscription + custom codedone
Per-domain rate limiting (so you don't hammer one host)wire it yourselfdone
Distinguishing real 403 from "you got blocked" 403guess and checkdone
Detecting soft 404s (200 OK + "not found" body)regex / heuristic per templatedone
Retry classification (transient vs permanent)tune for weeksdone
Long-running job state (resume after crash)Redis + queue + worker infradone
Engineer time, weeks 1-4$$$nothing, ship today

If you've already lost a weekend to httpx + proxy rotation, you know what we're talking about.

Pricing

  • First month on us: 15,000 URL checks on the Starter plan, no credit card. The first time an API or SDK integration runs successfully, the trial grows to a month of Pro: 50,000 URL checks, once per account.
  • After that: 300 URL checks a month are included on every account.
  • Starter: $9/month or $90/year, 15,000 URLs/month
  • Pro: $29/month or $290/year, 50,000 URLs/month
  • Agency: $99/month or $990/year, 200,000 URLs/month

Scheduled checks, with email, Slack and webhook alerts, are included on every plan. One-time credit packs start at $5 for 3,000 checks, and pack credits roll over. Current prices: https://bulkurlchecker.com/#pricing

Links

Stability

The SDK follows semver. While we're at 0.x, breaking changes can land in minor releases (we'll always note them in CHANGELOG.md). Once we hit 1.0 you can pin major versions safely.

License

MIT. See LICENSE.

来源:README.md,提交 c9b4cf9

工具

5

submit_urls

Submit URLs for checking

Submits a list of URLs to be checked and returns a job_id. Lists of up to about 200 URLs complete inline, waiting up to 60 seconds, and the results are returned directly. Larger lists return immediately with the job_id alone, and their results become available as the job progresses.

输入参数urls必填

get_job_status

Get job status

Get the current status and progress of a job.

输入参数job_id必填

get_job_results

Get job results

Fetch paginated results for a job. Each result has the URL, HTTP status code (null if unreachable), response time in ms, and an error message if the check failed.

输入参数limitjob_id必填offset

get_verified_domains

Get verified domains

Lists the domains this account has proven ownership of. Checks against a verified domain run substantially faster than checks against an unverified one. Verification is interactive, requiring a DNS TXT record or a meta tag, and is done in the web dashboard rather than through this API.

无需输入参数。

get_usage

Get credit balance

Returns the number of URL checks currently available on this account.

无需输入参数。

版本历史

2
  1. v1.0.1最新Oct 18, 2026
  2. v1.0.0Sep 16, 2026

评分

已满足适用检查项的 100%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通必需25 分
  • 已声明认证方式必需10 分
  • 已列出工具必需15 分
  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分