Skip to main content
ClaudeWave
carlosofscience avatar
carlosofscience

bulkurlchecker-python

Ver en GitHub

Python client for the Bulk URL Checker API

ToolsRegistry oficial0 estrellas0 forks● PythonMITActualizado 5d ago
ClaudeWave Trust Score
87/100
✓ Trusted
Passed
  • ✓Open-source license (MIT)
  • ✓Actively maintained (<30d)
  • ✓Clear description
  • ✓Documented (README)
Last scanned: 10/18/2026
Get started
Method: Clone
Terminal
git clone https://github.com/carlosofscience/bulkurlchecker-python
1. Clone the repository.
2. Follow the README for installation and usage instructions.
Casos de uso

Resumen de Tools

# bulkurlchecker

[![PyPI version](https://img.shields.io/pypi/v/bulkurlchecker.svg)](https://pypi.org/project/bulkurlchecker/)
[![Python versions](https://img.shields.io/pypi/pyversions/bulkurlchecker.svg)](https://pypi.org/project/bulkurlchecker/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)

Python client for the [Bulk URL Checker](https://bulkurlchecker.com) 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 accepted
results.completed_urls    # how many it finished checking
results.duplicates_removed
results.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 == True
results.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 stdout
bulkurlchecker check urls.txt > report.csv

# Pipe from anywhere
sitemap-extractor mydomain.com | bulkurlchecker check - --output jsonl > report.jsonl

# Only show broken URLs, ad-hoc input
bulkurlchecker 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 method
done = client.wait_until_done(job.job_id, timeout=3600)

# Stream results in pages
for 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, request
from 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:

| Problem | Rolling your own | This SDK |
|---|---|---|
| Concurrency | `asyncio` + careful semaphores | done |
| Proxy rotation across residential IPs | $90+/mo Webshare / Bright Data subscription + custom code | done |
| Per-domain rate limiting (so you don't hammer one host) | wire it yourself | done |
| Distinguishing real 403 from "you got blocked" 403 | guess and check | done |
| Detecting soft 404s (200 OK + "not found" body) | regex / heuristic per template | done |
| Retry classification (transient vs permanent) | tune for weeks | done |
| Long-running job state (resume after crash) | Redis + queue + worker infra | done |
| 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

- [Web app](https://app.bulkurlchecker.com)
- [REST API reference](https://bulkurlchecker.com/developers)
- [OpenAPI spec](https://api.bulkurlchecker.com/openapi.json)
- [GitHub](https://github.com/carlosofscience/bulkurlchecker-python)
- [Changelog](CHANGELOG.md)

## 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](LICENSE).

Lo que la gente pregunta sobre bulkurlchecker-python

¿Qué es carlosofscience/bulkurlchecker-python?

+

carlosofscience/bulkurlchecker-python es tools para el ecosistema de Claude AI. Python client for the Bulk URL Checker API Tiene 0 estrellas en GitHub y su última actualización registrada es del 2026-10-12.

¿Cómo se instala bulkurlchecker-python?

+

Puedes instalar bulkurlchecker-python clonando el repositorio (https://github.com/carlosofscience/bulkurlchecker-python) o siguiendo las instrucciones del README en GitHub. ClaudeWave también te ofrece bloques de instalación rápida en esta misma página.

¿Es seguro usar carlosofscience/bulkurlchecker-python?

+

Nuestro agente de seguridad ha analizado carlosofscience/bulkurlchecker-python y le ha asignado un Trust Score de 87/100 (tier: Trusted). Revisa el desglose completo de comprobaciones superadas y flags en esta página.

¿Quién mantiene carlosofscience/bulkurlchecker-python?

+

carlosofscience/bulkurlchecker-python es mantenido por carlosofscience. La última actividad registrada en GitHub es del 2026-10-12, con 2 issues abiertos.

¿Hay alternativas a bulkurlchecker-python?

+

Sí. En ClaudeWave puedes explorar tools similares en /categories/tools, ordenados por popularidad o actividad reciente.

Despliega bulkurlchecker-python en tu cloud

Lleva este repo a producción en minutos. Cada plataforma genera su propio entorno con variables de entorno editables.

¿Mantienes este repo? Añade un badge a tu README

Pega el badge en tu README de GitHub para mostrar que está auditado por ClaudeWave. Cada badge enlaza de vuelta a esta página y muestra el Trust Score actual.

Featured on ClaudeWave: carlosofscience/bulkurlchecker-python
[![Featured on ClaudeWave](https://claudewave.com/api/badge/carlosofscience-bulkurlchecker-python)](https://claudewave.com/repo/carlosofscience-bulkurlchecker-python)
<a href="https://claudewave.com/repo/carlosofscience-bulkurlchecker-python"><img src="https://claudewave.com/api/badge/carlosofscience-bulkurlchecker-python" alt="Featured on ClaudeWave: carlosofscience/bulkurlchecker-python" width="320" height="64" /></a>
multica-ai
andrej-karpathy-skills
6mo ago

A single CLAUDE.md file to improve Claude Code behavior, derived from Andrej Karpathy's observations on LLM coding pitfalls.

220.7k22.2k
ToolsInstall
nextlevelbuilder
ui-ux-pro-max-skill
3d ago

An AI skill that provides design intelligence for building professional UI/UX across multiple platforms.

136.9k14.5kPython
Toolsai-skillsantigravityInstall
JuliusBrussee
caveman
today

🪨 why use many token when few token do trick. Viral skill + proxy for coding agents that cuts 65% of tokens by talking like a caveman.

113.3k6.6kGo
ToolsaianthropicInstall
BerriAI
litellm
today

The fastest, litest AI Gateway. Rust core with Python SDK. Call 100+ LLM APIs in OpenAI (or native) format with cost tracking, guardrails, load balancing, and logging [Bedrock, Azure, OpenAI, Anthropic, OpenAI, VertexAI, vLLM, Nvidia NIM]

61.5k12.4kPython
Toolsai-gatewayanthropicInstall
Alishahryar1
free-claude-code
today

Use Claude Code, Codex, VSCode, Pi, and OpenCode (and 6 other harnesses) for free (1.3B+ free tokens) from your terminal, app, IDE, or phone, and now from the browser with native browser sessions (multi-harness + multi-model) like OpenClaw (voice supported + ToS friendly)

61.3k9.6kPython
ToolsInstall
router-for-me
CLIProxyAPI
today

Wrap Antigravity, ChatGPT Codex, Claude Code, Grok Build, Muse Code, Devin as an OpenAI/Gemini/Claude/Codex compatible API service, allowing you to enjoy the free Gemini Series, GPT Series, Grok Series, Claude model through API

55.5k8.5kGo
Toolsantigravityclaude-codeInstall