RankParse

Response format

The JSON envelope every RankParse endpoint returns, plus pagination, empty results, partial results, caching and data freshness.

Every billable endpoint answers with JSON. Successful responses share one envelope: the payload sits in data, and credit accounting sits next to it. Errors use a different, smaller shape described in Errors.

The envelope

GET /v1/backlinks?domain=stripe.com&limit=2
{
  "domain": "stripe.com",
  "data": [
    { "from_domain": "example-blog.com", "from_url": "https://example-blog.com/payments", "to_url": "https://stripe.com/", "anchor_text": "Stripe", "rel": null, "link_type": "dofollow", "crawled_at": "2026-02-11" },
    { "from_domain": "dev-news.io", "from_url": "https://dev-news.io/tools", "to_url": "https://stripe.com/docs", "anchor_text": "payments API", "rel": null, "link_type": "dofollow", "crawled_at": "2026-03-02" }
  ],
  "total": 18342,
  "limit": 2,
  "credits_used": 2,
  "credits_remaining": 98
}

The values above are illustrative. The field names are real. Each endpoint page lists the exact fields inside data.

Envelope fields

FieldTypePresent onMeaning
dataobject or arrayAlwaysThe result. Lists for row-based endpoints, an object for single-record endpoints.
domainstringDomain-level endpointsThe domain you sent, lowercased and trimmed. Domains must be bare hostnames such as stripe.com, with no scheme, path or port.
urlstringURL-level endpoints (page-seo, schema-markup, page-performance)The URL you asked about.
totalintegerRow-based endpointsHow many matching rows exist, which can be more than the rows returned.
limitintegerRow-based endpointsThe limit that was requested (defaults to 100).
credits_usedintegerAlwaysCredits this call cost after any refund. 0 means you were not charged.
credits_remainingintegerAlwaysYour workspace balance after this call.
partialbooleanEndpoints that can degradetrue when part of the answer timed out. See Partial results.
crawl_releasestringcompetitor-gap, link-auditThe snapshot the answer was built from. See Data freshness.

Not every endpoint returns every field. A field that does not apply is omitted rather than sent as null, so check for presence instead of assuming it exists.

Some endpoints add their own top-level fields next to the envelope. For example outbound-links adds summary, sitemap adds sitemap_url and source, schema-markup adds types and block_count, and competitor-gap adds vs, returned, scored and budget_ms. These are documented on each endpoint page.

Credit fields are always accurate

credits_used reports what you were actually billed for this call, not the list price. A call that was refunded in full reports credits_used: 0. Read credits_remaining to track your balance without a separate request. See Credits for the billing rules.

Pagination

Row-based endpoints use limit to cap the number of rows returned.

ParameterDefaultMaximumBehavior
limit1001000Values above 1000 are silently clamped to 1000. A missing, zero or non-numeric value falls back to 100, and values below 1 are raised to 1.
  • limit controls how many rows come back and does not change the price. A call with limit=1000 costs the same as limit=10.
  • Compare total with the length of data to see whether more rows exist than you received.
  • competitor-gap has a default limit of 50 instead of 100.
  • The link graph endpoints return the top rows ranked by the endpoint's own ordering and do not accept offset. To get a different slice, use the filters on the endpoint (for example sort and from_domain on backlinks).
  • Offset-based paging exists on a few account and rank tracking routes (/v1/usage, /v1/rank-tracking/keywords, /v1/rank-tracking/rankings, /v1/rank-tracking/alerts). Those pages document limit and offset individually.

The limit echoed back in the envelope is the value you sent, not the clamped value. If you request limit=5000, the response says 5000 but at most 1000 rows are returned. Use the length of data as the truth.

Empty results

A domain with no data is a valid answer, not an error. You get HTTP 200 with an empty data array and a charge as usual:

{
  "domain": "brand-new-site.example",
  "data": [],
  "total": 0,
  "limit": 100,
  "credits_used": 2,
  "credits_remaining": 96
}

RankParse never returns 404 for "no data". A 404 means the route or a resource id you named does not exist.

Partial results

Some endpoints run several queries against a time budget. When one of them does not finish in time, RankParse returns what it has and sets partial: true instead of failing the whole request.

{
  "domain": "large-site.example",
  "data": [ { "anchor_text": "large site", "link_count": 8120, "domain_count": 940 } ],
  "total": 1,
  "limit": 100,
  "partial": true,
  "credits_used": 2,
  "credits_remaining": 90
}

What partial means in practice:

  • The data you received is correct but may be incomplete. Treat the missing portion as "unknown", not as zero.
  • Partial answers are never cached. The same request can be retried and may return a complete answer.
  • Where partial appears. domain-authority, anchor-text, top-pages, site-explorer and link-audit include partial only when it is true. similar-domains and competitor-gap always include it as true or false.
  • Billing. A partial answer is still billed at the normal price, with one exception: domain-authority refunds its credit when the authority score itself could not be read (data.score is null and credits_used is 0).

When domain-authority returns partial: true, the fields score, referring_domains, total_host_count and health_score are null, never 0. Do not store them as zero.

Caching

Link graph answers are cached in Cloudflare KV for 30 days, keyed by crawl release, endpoint, domain and the parameters that change the result. Caching is a latency optimization only:

  • Cache hits are billed exactly like misses. The charge happens before the cache is checked, so a cached answer costs the same credits.
  • Cached answers are faster, because they skip the data query.
  • You cannot disable or bust the cache from the request. Data is tied to a crawl release, so a cached answer is still the same data a fresh query would return.
  • The response never says whether it was cached. Do not depend on a cached field.

Live endpoints (page-seo, tech-stack, site-health, sitemap, schema-markup) fetch the target site on every request, and crawl-history queries the Wayback Machine. page-performance caches each URL and strategy pair for 24 hours.

Data freshness and crawl_release

RankParse link graph data comes from pre-processed public web data built from periodic snapshots, not from a continuous feed. A snapshot is a point in time, so backlinks, anchor text, referring domains, top pages and domain authority describe the web as of that snapshot, not as of today.

  • The current snapshot is cc-main-2026-jan-feb-mar (January to March 2026).
  • The snapshot is a single server-side setting, so the link graph endpoints are all served from the same release.
  • crawl_release is returned by competitor-gap and link-audit. On other endpoints the release is not echoed in the body.

Live endpoints (page-seo, tech-stack, site-health, sitemap, schema-markup, page-performance) reflect the site right now. tech-stack also merges in detections from the link graph for anything the live fetch did not see. Rank tracking and search console data come from your connected accounts and are covered in Rank tracking.

Not yet available

A few endpoints exist so your integration can target a stable URL, but the data is not produced yet. They return 200, charge nothing, and say so in both data and the top level:

GET /v1/link-velocity?domain=stripe.com
{
  "domain": "stripe.com",
  "data": { "status": "not_yet_available", "reason": "requires_2_crawl_releases" },
  "credits_used": 0,
  "credits_remaining": 100,
  "status": "not_yet_available",
  "reason": "requires_2_crawl_releases"
}
Endpointreason
link-velocity, new-links, lost-linksrequires_2_crawl_releases
internal-linksinternal_links_not_in_pipeline_v1

Check status before reading the rest of the response. See Not yet available.

Responses without the envelope

A few routes return a small custom body instead of the envelope:

RouteBody
GET /v1/credits{ "credits": 842 }
GET /v1/pricing{ "tiers": [ { "min": 0, "price_per_credit": 0.01 }, ... ] }
GET /v1/keys, POST /v1/keys, DELETE /v1/keys/:idKey management objects. See Account.

Rank tracking, Search Console, Google Ads and the approval inbox have their own response shapes, documented on their pages.

Request IDs

RankParse does not return a request ID header or body field. When you contact support about a failed call, include the endpoint, the parameters, the approximate time (UTC) and the code from the error body.

On this page