Docs/API

Broken Links & Crawled URLs

These endpoints return broken links and crawled URL data for a monitor with the broken links check enabled. To configure the broken links check settings (whitelist URLs, link types, etc.), use the monitors endpoint.

You'll need a monitor ID for this endpoint.

Example request:

$ OHDEAR_TOKEN="your API token"
$ curl https://ohdear.app/api/broken-links/1 \
    -H "Authorization: Bearer $OHDEAR_TOKEN" \
    -H 'Accept: application/json' \
    -H 'Content-Type: application/json'

All endpoints below follow the same authentication pattern.

GET /api/broken-links/{monitorId}

Returns all broken links from the latest completed crawl run. You can also fetch results from a specific past run by passing run_id (see check history).

Query parameters:

  • run_id (integer, optional) -- return results from a specific run instead of the latest. Get run IDs from the check history endpoint.

Here's what the response looks like:

{
  "data": [
    {
      "status_code": 404,
      "crawled_url": "https://example.com/broken",
      "relative_crawled_url": "/broken",
      "found_on_url": "https://example.com",
      "relative_found_on_url": "/",
      "link_text": "Click here",
      "type": "link",
      "error_message": null,
      "internal": true
    }
  ],
  "meta": {
    "run_id": 98765,
    "run_started_at": "2026-03-17T00:30:00+00:00",
    "run_ended_at": "2026-03-17T00:53:58+00:00"
  }
}
  • status_code: the HTTP status code returned by the broken link
  • crawled_url: the full URL of the broken link
  • relative_crawled_url: the relative path of the broken link
  • found_on_url: the page where the broken link was found
  • relative_found_on_url: the relative path of the page containing the broken link
  • link_text: the anchor text or alt text of the link
  • type: the kind of resource -- one of link, image, script, stylesheet, or og:image
  • error_message: a description of the error when the request failed entirely (e.g. DNS resolution failure, connection timeout), or null when a status code was received
  • internal: whether the broken link points to the same domain (true) or an external site (false)

The meta object contains information about which run the results come from:

  • run_id: the ID of the run
  • run_started_at: when the run started (ISO 8601, UTC), or null
  • run_ended_at: when the run completed (ISO 8601, UTC)

Get crawled URLs summary #

GET /api/crawled-urls/{monitorId}/summary

Returns a summary with counts of all URLs found during a crawl run, not just the broken ones. This is useful for understanding the scope of a crawl without fetching every URL.

Query parameters:

  • run_id (integer, optional) -- return results from a specific run instead of the latest. Get run IDs from the check history endpoint.
{
  "data": {
    "total": 1234,
    "internal": 800,
    "external": 434,
    "by_type": {
      "image": 250,
      "link": 900,
      "og:image": 14,
      "script": 40,
      "stylesheet": 30
    }
  },
  "meta": {
    "run_id": 98765,
    "run_started_at": "2026-03-17T00:30:00+00:00",
    "run_ended_at": "2026-03-17T00:53:58+00:00"
  }
}
  • total: the total number of URLs crawled
  • internal: URLs on the same domain as the monitor
  • external: URLs pointing to other domains
  • by_type: breakdown by resource type (link, image, script, stylesheet, og:image)

Get crawled URLs details #

GET /api/crawled-urls/{monitorId}/details

Returns a paginated list of all URLs found during a crawl run (100 per page). Each entry includes the same fields as the broken links response.

Query parameters:

  • run_id (integer, optional) -- return results from a specific run instead of the latest. Get run IDs from the check history endpoint.
  • page (integer, optional) -- the page number for pagination (defaults to 1).
{
  "data": [
    {
      "status_code": 200,
      "crawled_url": "https://example.com/page",
      "relative_crawled_url": "/page",
      "found_on_url": "https://example.com",
      "relative_found_on_url": "/",
      "link_text": "Some page",
      "type": "link",
      "error_message": null,
      "internal": true
    }
  ],
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 53,
    "per_page": 100,
    "to": 100,
    "total": 5230,
    "run_id": 98765,
    "run_started_at": "2026-03-17T00:30:00+00:00",
    "run_ended_at": "2026-03-17T00:53:58+00:00"
  },
  "links": {
    "first": "/?page=1",
    "last": "/?page=53",
    "prev": null,
    "next": "/?page=2"
  }
}
Was this page helpful?

Feel free to reach out via [email protected] or on X via @OhDearApp if you have any other questions. We'd love to help!