Add broken link detection to your apps, pipelines and workflows in minutes. Submit any URL and receive structured JSON — every link's HTTP status, category and source page, ready to process programmatically.
From sign-up to your first JSON response in under five minutes.
Include your API key as a Bearer token in the
Authorization header. Always call the API
from your server — never from browser code, where the
key would be visible in source.
POST any URL with a crawl depth of 1, 2 or 3.
Depth 1 checks links on the target page.
Depth 2–3 follow and check linked pages too.
Receive structured JSON with every link's URL, HTTP status code,
category (ok / broken / redirect),
link text and the page it was found on.
Copy any example below — replace sk_live_YOUR_KEY_HERE
with your API key and you're ready to go.
curl -X POST 'https://www.sightful.info/api/v1/scan' \
-H "Authorization: Bearer sk_live_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{ "url": "https://example.com", "depth": 1 }'// Node.js — keep your API key on the server, never in browser code
const response = await fetch('https://www.sightful.info/api/v1/scan', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_YOUR_KEY_HERE',
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: 'https://example.com',
depth: 1,
}),
});
const data = await response.json();
// Filter to broken links only
const broken = data.results.filter(r => r.category === 'broken');
console.log(`Found ${broken.length} broken link(s)`);import requests
response = requests.post(
'https://www.sightful.info/api/v1/scan',
headers={
'Authorization': 'Bearer sk_live_YOUR_KEY_HERE',
'Content-Type': 'application/json',
},
json={
'url': 'https://example.com',
'depth': 1,
},
)
data = response.json()
# Filter to broken links only
broken = [r for r in data['results'] if r['category'] == 'broken']
print(f"Found {len(broken)} broken link(s)"){
"url": "https://example.com",
"depth": 1,
"pages_crawled": 1,
"hit_page_limit": false,
"hit_time_limit": false,
"js_rendering": null,
"results": [
{
"url": "https://example.com/about",
"source_page": "https://example.com",
"link_text": "About Us",
"status": 200,
"category": "ok"
},
{
"url": "https://example.com/old-page",
"source_page": "https://example.com",
"link_text": "Read more",
"status": 404,
"category": "broken"
},
{
"url": "https://example.com/signin",
"source_page": "https://example.com",
"link_text": "Sign in",
"status": 301,
"category": "redirect"
}
],
"meta": {
"tier": "hobbyist",
"calls_this_month": 1,
"calls_remaining": 499,
"resets_at": "2026-07-01T00:00:00+00:00"
}
}Every response includes three headers so your application can track and respect quota without parsing the response body. Monthly counters reset on the first of each calendar month (UTC).
| Header | Type | Description |
|---|---|---|
X-RateLimit-Limit |
integer | Your tier's monthly call cap (500 / 5,000 / 25,000). |
X-RateLimit-Remaining |
integer | Calls remaining until the next reset. Never goes below 0. |
X-RateLimit-Reset |
Unix timestamp | UTC time (seconds since epoch) when your monthly counter resets to full. |
When your monthly quota is exhausted the API returns HTTP 429:
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 500
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1751328000
{
"error": "Monthly call limit of 500 reached. Resets on Wed Jul 01 2026.",
"code": "RATE_LIMIT_EXCEEDED",
"meta": {
"tier": "hobbyist",
"calls_this_month": 500,
"limit": 500,
"resets_at": "2026-07-01T00:00:00+00:00"
}
}
All error responses share the same shape: an error string
for humans and a code string for machines.
Some errors include a meta object with additional context.
| HTTP status | Code | Meaning |
|---|---|---|
| 400 | MISSING_URL |
Request body did not include a url field. |
| 400 | INVALID_URL |
The url value could not be parsed, or uses a scheme other than http:// or https://. |
| 401 | UNAUTHORIZED |
The Authorization header is missing, malformed, or the key is inactive or does not exist. |
| 403 | PRIVATE_URL_BLOCKED |
The target URL resolves to a private or internal IP address. Only publicly accessible URLs may be scanned. |
| 403 | DEPTH_NOT_ALLOWED |
The requested depth exceeds your tier's maximum. Hobbyist: 1, Developer: 2, Professional: 3. |
| 429 | RATE_LIMIT_EXCEEDED |
Monthly call quota exhausted. Check X-RateLimit-Reset for when it refills, or upgrade your plan. |
| 500 | SERVICE_ERROR |
Authentication service temporarily unavailable. Retry with exponential back-off. |
All plans include structured JSON responses, API key management with rotation, and rate-limit headers on every response.