Skip to content
SEOtoolsAPI
APIs Documentation Pricing FAQ Sign in

API documentation

API reference

Use SEOtoolsAPI for domain metrics, backlinks, competitor discovery and keyword research. Lookups return JSON directly. Competitor and gap analyses return an analysis ID for the shared status endpoint. All endpoints use HTTPS and the same account API keys.

Use batch lookups to check up to 25 domains, filters and sorting to select relevant backlinks, and referring domains to summarize the websites linking to a target. Try Domain Data or Backlinks in the live demo without an account, using its separate trial allowance.

AuthenticationEndpointsDomain DataBatch lookupsLink queriesReferring domainsCompetitorsRanking keywordsKeyword gapsKeyword metricsAnalysis statusResponsesUsage costsErrors

Authentication

Create an account or sign in, then generate an API key in your dashboard. The full key is displayed once. Store it securely.

Send the key in the Authorization: Bearer header. Use HTTPS and the base URL https://seotoolsapi.com/api/v1/. API keys belong in server-side code or environment variables, never in a public browser script or query string.

cURL
curl --get "https://seotoolsapi.com/api/v1/domain-data" \
  --data-urlencode "domain=example.com" \
  --header "Authorization: Bearer $SEOTOOLS_API_KEY"

API keys contain a two-character checksum to detect common input errors. Authentication verifies the full key.

Endpoints

Domain metrics and link endpoints accept GET with a domain parameter, such as example.com. Ranking keyword lookups accept either a domain or a page URL through their respective routes. Domain Data batches, competitor discovery, gap analyses and keyword metrics accept POST with uncompressed UTF-8 JSON. Hostname inputs omit the scheme, path, port and IP address. Hostnames are lowercased; a trailing dot and leading www. are removed above the registrable domain. Page URLs preserve their host and path. Use ASCII punycode for international names if PHP intl is unavailable.

Input validation checks hostname syntax and public-suffix structure. Supply a registrable domain or a hostname beneath one; co.uk alone is not enough. The normalized ASCII name may contain up to 253 characters, with up to 63 in each label. Empty labels, repeated trailing dots, control characters, whitespace inside the hostname and numeric suffixes are rejected with 400 invalid_domain.

Use only the documented query parameters, once each. Duplicate names, array values and unsupported parameters return 400 invalid_parameters. Query strings may contain up to 8,192 bytes. Domain input may contain up to 1,024 UTF-8 bytes before normalization. Invalid inputs do not consume your monthly unit allowance.

Available API methods, routes and returned metrics
MethodEndpointWhat it returns
GET/domain-dataDomain Authority, homepage Page Authority, Spam Score, Gravity Score, registration month, domain age and backlink counts in one response.
POST/domain-data/batchDomain Data for 1 to 25 domains, with individual results, errors and quota accounting.
GET/backlinksExternal backlinks with follow, target URL, observation date and authority filters, sorting and cursor pagination.
GET/referring-domainsDistinct registrable referring domains with stored scores, matching link counts and observation dates.
GET/spam-scoreThe domain’s Spam Score, on a 0 to 100 scale.
POST/competitorsQueue evidence-supported business/product competitor discovery.
GET/domain-keywordsObserved ranking keywords and estimated keyword traffic for a domain.
GET/page-keywordsObserved ranking keywords for a specific page URL.
POST/keyword-gapQueue content, ranking or combined keyword opportunity analysis.
POST/keyword-metricsSearch volume, CPC, advertising competition and trends for 1 to 100 keywords.
GET/analyses/{analysis_id}Read an account-owned analysis and its result without consuming monthly units.

Domain Data

GET /api/v1/domain-data?domain=example.com combines Domain Authority, homepage Page Authority, Spam Score, Gravity Score, registration month and age in whole months. Gravity Score ranges from 0 to 100. Its backlink_counts object contains total inbound links, referring domains, referring IP addresses, referring subnets and inbound links from .edu and .gov sites. Unknown values are null; known zeros remain zero. Scores and backlink counts describe the normalized requested hostname. Domain age uses its registrable domain. On standard accounts, one successful combined request uses one unit from your allowance.

This endpoint returns counts. Use /backlinks for individual links and pagination. Domain Data accepts only the required domain parameter, a DNS hostname such as example.com or news.example.com. It has no pagination. See the complete JSON example and try requests in four languages on the front page.

Read how Gravity Score works for host scope, link evidence, authority propagation, spam controls and score interpretation.

cURL
curl --get "https://seotoolsapi.com/api/v1/domain-data" \
  --data-urlencode "domain=example.com" \
  --header "Authorization: Bearer $SEOTOOLS_API_KEY"

Backlinks and pagination

GET /api/v1/backlinks?domain=example.com returns external backlinks for the requested domain.

A registrable domain includes its subdomains. A specific subdomain queries only that host and its nondefault ports. The usual hostname normalization applies, including removal of a leading www. above the registrable domain. Internal links between hosts of the same registrable domain and links marked lost are excluded.

Use limit from 1 to 5,000, default 100. When pagination.has_more is true, pass its next_cursor as after with the same domain, filters and sort. The default order uses target and source URL IDs. Use sort=authority or a date sort to change it. Each successful page uses one unit from your allowance.

cURL
curl --get "https://seotoolsapi.com/api/v1/backlinks" \
  --data-urlencode "domain=example.com" \
  --data-urlencode "limit=100" \
  --header "Authorization: Bearer $SEOTOOLS_API_KEY"

Batch Domain Data lookups

POST /api/v1/domain-data/batch accepts an uncompressed UTF-8 JSON object containing a domains array of 1 to 25 entries. Set Content-Type: application/json. The body may contain up to 65,536 bytes. Query parameters and additional object fields are rejected.

cURL
curl "https://seotoolsapi.com/api/v1/domain-data/batch" \
  --header "Authorization: Bearer $SEOTOOLS_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"domains":["example.com","news.example.com"]}'

A valid batch returns HTTP 200 with request_id, summary (total, successful and failed), and an ordered results array. Each item contains its zero-based index, normalized domain, status, and its own request_id, followed by the usual Domain Data fields or an error object. Invalid domains have domain: null. A retryable item can include retry_after in seconds.

Every successful item uses one monthly unit, including unknown metrics. Invalid and failed items use no monthly allowance. Every admitted lookup follows the same account-wide minute limit as single requests. Repeated domains are processed as separate entries and successful repeats each use one unit. Statistics label these lookups as Domain Data batch items.

The batch stops starting lookups after 45 seconds, or after an authentication, account-limit or service failure. An in-progress lookup keeps its existing timeout. Remaining valid entries return 503 batch_time_limit or batch_not_processed with the stopping HTTP status and use no allowance. Retry only failed or unprocessed items to avoid paying for successful items again. Smaller batches are recommended for domains that are not cached and for hosts with shorter HTTP timeouts. A rejected API key returns HTTP 401 before the first valid lookup.

Partial batch response

This illustrative HTTP 200 response contains one successful lookup and one temporary failure. It uses one monthly unit. Retry the item at index 1 after the indicated delay; the first item is already complete.

response.json
{
  "request_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  "summary": {
    "total": 2,
    "successful": 1,
    "failed": 1
  },
  "results": [
    {
      "index": 0,
      "domain": "example.com",
      "status": 200,
      "request_id": "11111111111111111111111111111111",
      "domain_authority": 72,
      "page_authority": 64,
      "spam_score": 3,
      "gravity_score": 64,
      "scale": 100,
      "registration_month": "2000-01",
      "age_months": 322,
      "backlink_counts": {
        "total": "54210",
        "referring_domains": 824,
        "referring_ips": 601,
        "referring_subnets": 452,
        "edu": 12,
        "gov": 3
      }
    },
    {
      "index": 1,
      "domain": "news.example.com",
      "status": 503,
      "request_id": "22222222222222222222222222222222",
      "error": {
        "code": "upstream_unavailable",
        "message": "The data provider could not complete this lookup. This request does not use your allowance."
      },
      "retry_after": 30
    }
  ]
}

Backlink filtering and sorting

Both /backlinks and /referring-domains accept the filters below. Filters describe the locally available live external links. A successful query with no matches returns an empty array and uses one request.

Link query parameters
ParameterAccepted values and behavior
followall (default), followed, or nofollow. Followed excludes nofollow, UGC and sponsored flags. Nofollow selects the nofollow flag specifically.
target_urlHTTP or HTTPS URL in the requested domain scope. Matches its normalized host, port, path and retained query string. Schemes share the same stored URL. Usual tracking parameters and fragments are removed; www in this URL is preserved.
first_seen_from, last_seen_fromInclusive observation date in YYYY-MM-DD format, from 2020-01-01 through the supported 65,535-day storage range.
min_source_authorityInteger from 0 to 100. Requires a known Domain Authority at least this high. Backlinks uses the source host; referring domains uses the registrable source domain.
one_per_domainBacklinks only: true or false (default). Returns the first matching link per registrable referring domain in the selected sort order, across all pages.
sortBacklinks: id (default), authority, first_seen, or last_seen. Referring domains: domain (default), authority, backlinks, first_seen, or last_seen.

ID and domain sorts are ascending. Scores, counts and dates sort descending, with known scores before unknown scores and deterministic identifier tie-breaks. Sorted or filtered backlink rows also include referring_domain, source_domain_authority, source_gravity_score and source_spam_score. Scores come from stored source-host records and can be null; no additional provider lookup is made for each source.

Use limit from 1 to 5,000 and pass pagination.next_cursor as after. Keep the same endpoint, domain, filters and sort on later pages. Page size may change. Existing unfiltered backlink requests keep their original cursor format. Queries read current data, so changes to links or scores between pages can affect results. A query that exceeds its database time budget returns an error without using the monthly allowance.

cURL
curl --get "https://seotoolsapi.com/api/v1/backlinks" \
  --data-urlencode "domain=example.com" \
  --data-urlencode "follow=followed" \
  --data-urlencode "one_per_domain=true" \
  --data-urlencode "min_source_authority=60" \
  --data-urlencode "sort=authority" \
  --header "Authorization: Bearer $SEOTOOLS_API_KEY"

Filtered backlink response

The example selects followed links from sources with a known Domain Authority of at least 60, with one link per referring domain. The source scores describe the linking host. The response below shows the core fields; provider refresh information can also be returned.

response.json
{
  "request_id": "33333333333333333333333333333333",
  "domain": "example.com",
  "backlinks": [
    {
      "source_url_id": "8589934593",
      "target_url_id": "4294967297",
      "source": "https://publisher.example/resources",
      "target": "https://example.com/guide",
      "source_host": "publisher.example",
      "target_host": "example.com",
      "anchor": "Useful guide",
      "title": "Resources",
      "nofollow": false,
      "flags": 16,
      "first_seen": "2026-10-29",
      "last_seen": "2026-11-01",
      "referring_domain": "publisher.example",
      "source_domain_authority": 80,
      "source_gravity_score": 50,
      "source_spam_score": 2
    }
  ],
  "pagination": {
    "limit": 100,
    "has_more": false,
    "next_cursor": null
  }
}

Referring domains

GET /api/v1/referring-domains?domain=example.com groups matching backlinks by their registrable source domain. Multiple linking subdomains and ports belong to one referring domain. The target scope follows the same registrable-domain and specific-host rules as backlinks.

cURL
curl --get "https://seotoolsapi.com/api/v1/referring-domains" \
  --data-urlencode "domain=example.com" \
  --data-urlencode "sort=backlinks" \
  --header "Authorization: Bearer $SEOTOOLS_API_KEY"

The response contains request_id, domain, referring_domains and pagination, plus the existing provider refresh information. Each referring-domain item contains domain, stored registrable-domain domain_authority, gravity_score and spam_score (integers or null), source_hosts (distinct linking hosts, including ports), and first_seen and last_seen dates.

Link counts are decimal strings: backlinks, followed_backlinks, nofollow_backlinks, ugc_backlinks and sponsored_backlinks. Attributes can overlap, so their counts should not be added together. Counts and dates describe links matching the active filters. Unknown page URLs can still contribute domain-level evidence. Scores use already stored metrics; unavailable root-domain metrics remain null.

These summaries cover the local graph, including imported observations. Domain Data backlink totals come from a separate provider dataset and need not equal the number of links or referring domains returned here. A complete provider snapshot may itself be a limited sample. Each successful result page uses one monthly unit.

response.json
{
  "request_id": "44444444444444444444444444444444",
  "domain": "example.com",
  "referring_domains": [
    {
      "domain": "publisher.example",
      "domain_authority": 80,
      "gravity_score": 50,
      "spam_score": 2,
      "source_hosts": 2,
      "first_seen": "2026-10-01",
      "last_seen": "2026-11-01",
      "backlinks": "12",
      "followed_backlinks": "8",
      "nofollow_backlinks": "3",
      "ugc_backlinks": "1",
      "sponsored_backlinks": "0"
    }
  ],
  "pagination": {
    "limit": 100,
    "has_more": false,
    "next_cursor": null
  }
}

Competitor discovery

POST /api/v1/competitors discovers competing businesses/products, with explanations and captured page evidence. It combines search results, available ranking keywords, product suggestions and alternatives articles, then assesses candidate product pages. It is best suited to English-language software and web products. Supply exactly one of domain or url, a supported country, and an optional limit from 1 to 25 (default 10). A product URL preserves its specific path. Set include_adjacent: true to include related products with a different main job.

cURL
curl "https://seotoolsapi.com/api/v1/competitors" \
  --header "Authorization: Bearer $SEOTOOLS_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: example-competitors-001" \
  --data '{"domain":"example.com","country":"us","limit":10}'

The HTTP 202 response includes the analysis ID, status URL, deadline and quoted/reserved unit cost. This abbreviated example shows an accepted request:

response.json
{
  "request_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  "analysis_id": "an_0123456789abcdef0123456789abcdef",
  "type": "competitors",
  "status": "queued",
  "status_url": "/api/v1/analyses/an_0123456789abcdef0123456789abcdef",
  "usage": {
    "quoted_units": 25,
    "charged_units": 0,
    "reserved_units": 25  },
  "result": null,
  "error": null
}

Completed results contain a target profile and competitors entries with name, domain, url, relationship (direct, alternative or adjacent), relevance_score, reason and evidence. Each accepted candidate includes an excerpt found in its captured product page. Scores range from 0 to 1 and are internal AI-supported relevance assessments. Coverage identifies how many candidates were found and checked; a requested limit does not guarantee that many verified matches.

Domain and page ranking keywords

GET /api/v1/domain-keywords accepts domain. GET /api/v1/page-keywords accepts an absolute HTTP or HTTPS url. Both require country and accept limit from 1 to 100 (default 20). These are bounded provider observations of ranking positions and estimated keyword traffic. Domain observations do not establish a landing page; page observations apply to the requested page.

cURL
curl --get "https://seotoolsapi.com/api/v1/domain-keywords" \
  --data-urlencode "domain=example.com" \
  --data-urlencode "country=us" \
  --data-urlencode "limit=20" \
  --header "Authorization: Bearer $SEOTOOLS_API_KEY"
cURL
curl --get "https://seotoolsapi.com/api/v1/page-keywords" \
  --data-urlencode "url=https://example.com/product/" \
  --data-urlencode "country=us" \
  --data-urlencode "limit=20" \
  --header "Authorization: Bearer $SEOTOOLS_API_KEY"
response.json
{
  "request_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
  "subject": {
    "scope": "page",
    "domain": "example.com",
    "url": "https://example.com/product/"
  },
  "country": "us",
  "fetched_at": "2026-11-02T00:00:00Z",
  "observed_at": null,
  "cache_hit": false,
  "keywords": [
    {
      "keyword": "software uninstaller",
      "position": 7,
      "estimated_monthly_traffic": 120
    }
  ],
  "coverage": {
    "requested_limit": 20,
    "returned": 1,
    "complete": false
  },
  "usage": { "units": 1 }
}

Results have no cursor pagination: the requested limit selects a provider sample. Missing keywords mean not found in that sample. fetched_at records retrieval time; observed_at remains null because the provider collection date is unavailable. Traffic is estimated. Fresh ranking responses are reused for up to seven days, with empty samples refreshed after one day.

Keyword gap analysis

POST /api/v1/keyword-gap compares one target with 1 to 5 competitors. Supply exactly one of target domain or url, country, and either a competitors array of distinct domains/URLs or a completed, account-owned competitor_analysis_id. Reusing an analysis selects up to its first five competitors. Optional currency defaults to usd; limit accepts 1 to 100 and defaults to 25.

Use mode: content for phrases found in captured competitor content but absent from captured target content, rankings for observed ranking opportunities, or combined (default) for both. Product relevance is checked against literal target-page evidence before recommendations are returned. Available search metrics enrich approved keywords.

cURL
curl "https://seotoolsapi.com/api/v1/keyword-gap" \
  --header "Authorization: Bearer $SEOTOOLS_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: example-keyword-gap-001" \
  --data '{"url":"https://example.com/","competitors":["https://competitor-one.com/","https://competitor-two.com/"],"country":"us","currency":"usd","mode":"combined","limit":25}'

Submission returns HTTP 202. Read result.opportunities through the shared status endpoint when the analysis reaches completed or partial. Each item separates content_gap, ranking_status, captured content evidence, provider ranking observations, keyword metrics and the target relevance explanation. This abbreviated result illustrates those fields:

response.json
{
  "analysis_id": "an_11111111111111111111111111111111",
  "type": "keyword-gap",
  "status": "completed",
  "result": {
    "mode": "combined",
    "opportunities": [
      {
        "keyword": "bulk software uninstaller",
        "content_gap": true,
        "ranking_status": "not_observed_in_target_sample",
        "competitor_urls": ["https://competitor-one.com/"],
        "target_urls": [],
        "search_volume": 500,
        "relevance_score": 0.92,
        "opportunity_score": 78,
        "reason": "The target supports removing several applications.",
        "target_evidence": {
          "url": "https://example.com/",
          "excerpt": "Remove multiple applications in one operation."
        }
      }
    ],
    "coverage": { "complete": false, "language": "en" },
    "source_errors": []
  }
}

Ranking statuses are competitor_higher, target_observed, not_observed_in_target_sample, unavailable or not_requested. An unavailable target ranking source remains unavailable. Only an actual target page observation can establish target_urls. The opportunity score is an internal 0 to 100 prioritization measure using relevance, competitor content consensus, available volume and observed ranking differences. It does not measure organic difficulty or predict a ranking improvement.

Content coverage is one server-rendered page per supplied subject, using English phrase extraction; JavaScript-only text is not rendered. The analysis does not claim whole-site coverage. Incomplete sources are listed in source_errors. A partial result can still contain useful opportunities, with unknown metrics left null.

Keyword metrics

POST /api/v1/keyword-metrics accepts a keywords array containing 1 to 100 UTF-8 phrases, a supported country, and an optional currency (default usd). Each phrase is limited to 256 bytes, normalized for whitespace and case, and returned in input order. Duplicates remain separate results. Response rows are matched by normalized keyword identity; missing, conflicting or invalid provider rows remain unavailable.

cURL
curl "https://seotoolsapi.com/api/v1/keyword-metrics" \
  --header "Authorization: Bearer $SEOTOOLS_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"keywords":["software uninstaller","bulk software uninstaller"],"country":"us","currency":"usd"}'
response.json
{
  "request_id": "cccccccccccccccccccccccccccccccc",
  "country": "us",
  "currency": "usd",
  "fetched_at": "2026-11-02T00:00:00Z",
  "observed_at": null,
  "cache_hit": false,
  "keywords": [
    {
      "keyword": "software uninstaller",
      "search_volume": 500,
      "cpc": 1.25,
      "currency": "usd",
      "ads_competition": 0.35,
      "trend": [
        { "period": "2026-09", "search_volume": 480 },
        { "period": "2026-10", "search_volume": 520 }
      ],
      "status": "ok"
    },
    {
      "keyword": "bulk software uninstaller",
      "search_volume": null,
      "cpc": null,
      "currency": "usd",
      "ads_competition": null,
      "trend": [],
      "status": "unavailable"
    }
  ],
  "usage": { "units": 2 }
}

search_volume is a nonnegative integer or null; cpc is a nonnegative number or null in the requested currency; ads_competition ranges from 0 to 1 or is null. Trend rows are chronological monthly observations. Known zeros remain zero. Advertising competition describes paid search. Keyword metrics normally refresh after 30 days; batches with unavailable rows refresh after one day.

Supported country values: us, uk, ca, au, in, nz, za, ie, sg. Supported currency values: usd, gbp, cad, aud, eur, inr, nzd, zar, sgd. The same country is used across each analysis and its keyword metrics. Search page URLs must use standard HTTP or HTTPS ports, and fragments and common tracking parameters are removed.

Shared analysis status

GET /api/v1/analyses/{analysis_id} reads progress or results with any active API key owned by the submitting account. Unknown and other-account IDs return the same 404 error. Status is queued, running, completed, partial or failed. Results stay null while work or accounting finalization is unfinished. Completed and partial results include data; failed analyses include an error and release their reserved units.

cURL
curl "https://seotoolsapi.com/api/v1/analyses/an_0123456789abcdef0123456789abcdef" \
  --header "Authorization: Bearer $SEOTOOLS_API_KEY"

For a completed competitor analysis, the result contains entries such as the following. All numbers and websites in the documentation examples are illustrative.

response.json
{
  "analysis_id": "an_0123456789abcdef0123456789abcdef",
  "type": "competitors",
  "status": "completed",
  "usage": {
    "quoted_units": 25,
    "charged_units": 25,
    "reserved_units": 0
  },
  "result": {
    "competitor_type": "business_product",
    "competitors": [
      {
        "name": "Competing Product",
        "domain": "competitor-one.com",
        "url": "https://competitor-one.com/product/",
        "relationship": "direct",
        "relevance_score": 0.91,
        "reason": "Offers the same application-removal function.",
        "evidence": [
          {
            "type": "product_page",
            "url": "https://competitor-one.com/product/",
            "excerpt": "Remove multiple applications in one operation.",
            "fetched_at": "2026-11-02T00:00:00Z"
          }
        ]
      }
    ],
    "coverage": { "complete": false, "language": "en" },
    "source_errors": []
  },
  "error": null
}

Use the POST response’s status_url and poll at intervals of at least 15 seconds, observing rate-limit headers. Polling uses no monthly units. The processing window is 30 minutes from submission; queued time counts toward it. At most three analyses may be unfinished per account. The submitting key and account must remain active while processing. Actual processing time depends on page availability and queue load.

Both analysis POST routes accept an optional Idempotency-Key header of 8 to 128 ASCII letters, digits, periods, underscores, colons or hyphens. Reusing it with the same normalized input on the same account returns the same analysis with no new monthly cost or provider work. A different endpoint or input with that key returns 409. Retain the key when retrying an uncertain submission. A new key starts a new analysis.

Response format

These examples show the core response fields for each endpoint, including the requested metric and a request identifier.

Domain Data

response.json
{
  "request_id": "0123456789abcdef0123456789abcdef",
  "domain": "example.com",
  "domain_authority": 72,
  "page_authority": 64,
  "spam_score": 3,
  "gravity_score": 64,
  "scale": 100,
  "registration_month": "2000-01",
  "age_months": 322,
  "backlink_counts": {
    "total": "54210",
    "referring_domains": 824,
    "referring_ips": 601,
    "referring_subnets": 452,
    "edu": 12,
    "gov": 3
  }
}

Spam Score

response.json
{
  "request_id": "0123456789abcdef0123456789abcdef",
  "domain": "example.com",
  "spam_score": 3,
  "scale": 100
}

Backlinks

response.json
{
  "request_id": "0123456789abcdef0123456789abcdef",
  "domain": "example.com",
  "backlinks": [
    {
      "source_url_id": "8589934593",
      "target_url_id": "4294967297",
      "source": "https://publisher.example/resources",
      "target": "https://example.com/guide",
      "source_host": "publisher.example",
      "target_host": "example.com",
      "anchor": "Useful guide",
      "title": "Resources",
      "nofollow": false,
      "flags": 16,
      "first_seen": "2026-10-29",
      "last_seen": "2026-10-29"
    }
  ],
  "pagination": {
    "limit": 100,
    "has_more": false,
    "next_cursor": null
  }
}
API field names, descriptions and data types
FieldDescriptionJSON type
request_idUnique request identifier, also returned in X-Request-ID.string
domainNormalized hostname.string
registration_monthKnown registration month as YYYY-MM.string or null
age_monthsUTC calendar-month difference from the registration month.integer or null
domain_authorityDomain Authority score, from 0 to 100.integer or null
page_authorityHomepage Page Authority score, from 0 to 100.integer or null
spam_scoreDomain Spam Score, from 0 to 100.integer or null
gravity_scoreDomain Gravity Score, from 0 to 100. Included in Domain Data.integer or null
scaleMaximum Domain Authority, Page Authority, Spam Score and Gravity Score, always 100.integer

Domain Data counts

The combined response includes the score and age fields above, plus backlink_counts. Its total is a decimal string to preserve large counts. The remaining counts are integers from 0 to 4,294,967,295, or null when unavailable.

Domain Data backlink count descriptions and types
FieldDescriptionJSON type
backlink_countsSummary of inbound links and referring sources, with the fields below.object
backlink_counts.totalTotal external inbound links. A decimal string preserves unsigned 64-bit precision.string or null
backlink_counts.referring_domainsDistinct referring domains.integer or null
backlink_counts.referring_ipsDistinct referring IP addresses.integer or null
backlink_counts.referring_subnetsDistinct referring class C subnets.integer or null
backlink_counts.edu, backlink_counts.govInbound links from .edu and .gov domains.integer or null

Backlinks response fields

Backlinks responses contain the common request_id and domain fields, plus the fields below.

Backlink response field descriptions and JSON types
FieldDescriptionJSON type
backlinksThe current page of backlinks.array of objects
backlinks[].source, backlinks[].targetNormalized source/target URLs. Null for domain-level placeholders where the page is unknown. HTTP/HTTPS variants share one URL row; HTTPS is preferred once observed.string or null
backlinks[].source_host, backlinks[].target_hostHostnames, including a nondefault port when present.string or null
backlinks[].anchor, backlinks[].titleKnown anchor text and source-page title. Anchor text is limited to 255 UTF-8 bytes, title to 1,024. Unknown values are null.string or null
backlinks[].nofollowWhether the link carries the nofollow flag.boolean
backlinks[].flagsLink bit flags: 1 nofollow, 2 UGC, 4 sponsored, 8 image, 16 HTTPS source, 32 redirect, 64 imported/domain-level, 128 lost. Lost links are excluded from this endpoint.integer
backlinks[].first_seen, backlinks[].last_seenObservation dates as YYYY-MM-DD.string
backlinks[].source_url_id, backlinks[].target_url_id64-bit identifiers, encoded as strings to preserve precision.string
paginationContains limit (integer), has_more (boolean) and next_cursor (string or null). Pass next_cursor as after to request the next page.object

Rate limits and quotas

The Free plan includes 100 usage units per calendar month and 5 requests per minute. Standard account limits are shared by all keys. Monthly allowances reset at midnight UTC on the first day of the next month.

Plan allowances
PlanMonthly usage unitsRequests per minute
Free1005
Developer10,00060
Startup30,000120
Business50,000180

All plans include every API endpoint. Monthly allowances also apply to yearly billing. Paid subscriptions are currently unavailable; the pricing page shows monthly and yearly plan comparisons.

Endpoint usage unit costs
OperationMonthly units
Domain Data, Spam Score, Backlinks or Referring Domains1 per successful lookup or page, including unknown metrics or an empty result.
Domain Data batch1 per successful item; failed or unprocessed items use 0.
Domain or page ranking keywords1 per returned keyword, with a minimum of 1 for a successful lookup. The requested limit is reserved first; unused units are released.
Keyword metrics1 per submitted keyword, including duplicates and unavailable values. The provider request is deduplicated.
Competitor discovery25, reserved at submission and charged on a completed or partial result.
Keyword gap analysis50, reserved at submission and charged on a completed or partial result.
Analysis status or idempotent replay0 monthly units; authenticated minute limits still apply.

Failed lookups and analyses use no monthly units. Partial analyses include usable results and source-error details and use their quoted cost. Reserved units are unavailable for other requests until completion or release. Each Domain Data batch item and each status/replay HTTP request follows the shared minute limit. Cached successful lookups have the same unit cost as other successful lookups.

Authenticated responses include X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (Unix seconds), X-Monthly-Requests-Limit and X-Monthly-Requests-Remaining. The existing monthly header names are preserved and now describe usage units. A 429 includes Retry-After in seconds. Reservations reduce the remaining monthly allowance. Polling remains available at an exhausted monthly allowance, subject to the minute limit.

API keys owned by active administrators have no monthly quota or per-minute limit. Their requests are still authenticated and included in usage statistics. For these keys, the limit and remaining headers contain unlimited; X-RateLimit-Reset is omitted.

See requests by key and endpoint in your dashboard. Malformed and unauthenticated requests are not included in account statistics. Compare plan allowances and billing options on the pricing page.

Errors

Error responses include a request_id and an error object containing code and message.

API HTTP status codes
HTTP statusMeaning
400Invalid domain, JSON body, query parameters or cursor. Use each documented parameter once.
401Missing, invalid, expired or deleted API key, or an unavailable account.
404Unknown API endpoint.
405Unsupported method. Batch lookups use POST; other endpoints use GET.
413Batch body exceeds 65,536 bytes.
415Batch body does not use uncompressed UTF-8 application/json.
429Account minute limit or monthly allowance reached.
502The data request could not be completed.
503The service is temporarily unavailable or an item was not started within the batch time budget.

For 429 or a 503 with Retry-After, wait for that interval before retrying. Analysis POST requests return 202 when accepted. A 409 can indicate an idempotency conflict or an unfinished source analysis. Unknown and other-account analysis IDs return 404. A third unfinished analysis is allowed; another submission returns 429 until one finishes. Analysis status responses remain HTTP 200 when an owned job reaches failed; inspect its status and error fields.

SEOtoolsAPI

Domain metrics and backlinks for your applications.

Our APIsDocumentationGravity ScorePricingFAQ

© 2026 Great Software Company. All rights reserved.

Terms of usePrivacy policyRefund policy

Domain metrics, API keys and usage statistics. All in one place.