semust logo

API Platform

Backlinks API

Retrieve backlink profiles, referring domains, anchor texts, competitors and historical link growth for any domain, subdomain or page.

Retrieve backlink profiles, referring domains, anchor texts, competitors and historical link growth for any domain, subdomain or page. One endpoint serves eight different reports, selected with the type parameter.

Product page: Backlinks API.

Authentication

All requests require header-based authentication. Include your API credentials in every request.

HeaderTypeDescription
SEMUST-API-USERstringYour API user's username
SEMUST-API-PASSWORDstringYour API user's password

Create API credentials from the API Access page.

SEMUST-API-USER: your_username
SEMUST-API-PASSWORD: your_password

Report Types

The type parameter selects which report you get back. All eight share the same endpoint, authentication and pricing.

typeReturns
summaryOne metric block: totals, referring domains, spam scores and breakdowns
historyMonthly series of those same metrics
backlinksThe individual backlinks
referring_domainsDomains linking to the target, aggregated
anchorsAnchor texts, aggregated
competitorsDomains with overlapping backlink profiles
pagesThe target's own pages, ranked by backlinks received
timeseriesNew and lost counts over time

summary is the default. It returns a single row, so an accidental request without a type costs the minimum.

{
  "target": "example.com",
  "type": "backlinks",
  "limit": 100
}

Request Parameters

Send an application/json body. Parameters that do not apply to the chosen type are rejected rather than ignored, so a typo never silently returns something other than what you asked for.

Body

targetstringrequired

Domain, subdomain or page URL. Scheme and www. are removed automatically for domain lookups.

typestringdefault: summary

Which report to return. See Report Types above.

scopestringdefault: domain

domain includes every subdomain, host restricts to the exact host, url restricts to one page. With url the target must include http:// or https://.

statusstringdefault: live

live returns links still in place, lost returns links that disappeared, all returns both. Not accepted on history, timeseries or competitors — those reports have no link-status dimension.

limitintegerdefault: 100

Rows to return, 1–1000. Applies to the row-returning reports.

offsetintegerdefault: 0

Rows to skip, 0–20000. Use cursor to page beyond that.

cursorstring

Opaque pagination token from next_cursor. Only type: "backlinks" supports it. Cannot be combined with offset.

group_bystringdefault: none

none returns every backlink, domain returns one per referring domain, anchor returns one per anchor text. Only for type: "backlinks".

include_subdomainsbooleandefault: true

Include links pointing at subdomains of the target. Not accepted on history.

exclude_internalbooleandefault: true

Exclude links coming from the target's own domain. Not accepted on history or timeseries.

include_redirectsbooleandefault: true

Include links that reach the target through a redirect or canonical. Not accepted on history, timeseries or competitors.

filtersarray

Filter expression over the response fields. See Filters below.

order_byarray

Up to 3 sort rules, each "field,asc" or "field,desc".

date_fromstring

Start date, YYYY-MM-DD. For history and timeseries. Defaults to 12 months ago; earlier than 2019-02-01 is clamped.

date_tostring

End date, YYYY-MM-DD. Defaults to today.

granularitystringdefault: month

Bucket size for timeseries: day, week, month or year.

include_breakdownsbooleandefault: false

Include the links_by_* maps on every point of a history response. Off by default because it makes the payload considerably larger.

breakdown_limitintegerdefault: 25

How many entries to keep in each links_by_* map, 1–1000. Kept by descending count.

idempotency_keystring

Optional. Repeating a request with the same key within 24 hours returns the stored response at no charge, so a timed-out request can be retried safely.

Date range affects cost

history bills one row per month in the range. Leaving the dates out gives you the last 12 months rather than the full archive, which keeps an unspecified request cheap.

{
  "target": "example.com",
  "type": "backlinks",
  "scope": "domain",
  "status": "live",
  "limit": 100,
  "filters": [
    ["is_dofollow", "=", true],
    "and",
    ["source_domain_rate", ">=", 40]
  ],
  "order_by": ["source_domain_rate,desc"]
}

Filters

filters takes a condition, or an array of conditions joined by "and" / "or". A condition is [field, operator, value]. Nest arrays to combine both operators — a single group cannot mix them, which keeps precedence unambiguous.

Operators available depend on the field's type:

TypeOperators
boolean=, <>
integer<, <=, >, >=, =, <>, in, not_in
string=, <>, in, not_in, like, not_like, ilike, not_ilike, match, not_match, regex, not_regex
enum=, <>, in, not_in
datetime<, <=, >, >=, =

like patterns use % as the wildcard. Datetime values are RFC3339.

Limits: 8 conditions, 3 sort rules, 3 levels of nesting, 1000 characters for a regex, 255 for any other string.

GET /v1/backlinks/filters returns the filterable and sortable fields for every report type, with the operators each accepts — add ?type=backlinks for one report.

{
  "target": "example.com",
  "type": "backlinks",
  "filters": ["source_domain", "like", "%.edu"]
}

Code Examples

Complete examples fetching a backlink list in different languages.

curl -X POST https://data.semust.com/v1/backlinks \
  -H "SEMUST-API-USER: your_username" \
  -H "SEMUST-API-PASSWORD: your_password" \
  -H "Content-Type: application/json" \
  -d '{
    "target": "example.com",
    "type": "backlinks",
    "limit": 100,
    "filters": [["is_dofollow", "=", true]],
    "order_by": ["source_domain_rate,desc"]
  }'

Pagination

Row-returning reports accept offset up to 20,000. Beyond that, use the next_cursor value from the previous response as cursor on the next request. Cursors are tied to your account and to the exact query that produced them, so filters cannot change mid-scroll, and they expire after 30 minutes.

next_cursor is null when there are no further rows. Only type: "backlinks" returns one.

{
  "target": "example.com",
  "type": "backlinks",
  "limit": 1000
}

Response

Every report returns the same envelope. results holds the rows; summary returns a single result object instead.

total is an approximate count of everything matching your query, not the number of rows returned — use count for that.

{
  "success": true,
  "cached": false,
  "cost": 0.030360,
  "type": "backlinks",
  "target": "example.com",
  "scope": "domain",
  "total": 337785,
  "count": 100,
  "limit": 100,
  "next_cursor": "bl_4f2c8a91d0e34b7c9a15e8f60b2d7c43",
  "results": [
    {
      "source_url": "https://blog.example.de/seo-tools",
      "source_domain": "blog.example.de",
      "target_url": "https://example.com/",
      "target_domain": "example.com",
      "source_tld": "de",
      "anchor_text": "example seo tools",
      "anchor_type": "branded",
      "image_url": null,
      "image_alt": null,
      "context_before": "we recommend",
      "context_after": "for link research",
      "link_type": "text",
      "link_position": "content",
      "is_dofollow": true,
      "is_ugc": false,
      "is_sponsored": false,
      "rel_attributes": [],
      "via_redirect": false,
      "identical_links_count": 1,
      "is_new": false,
      "is_live": true,
      "is_broken": false,
      "first_seen": "2024-02-12T03:09:59Z",
      "last_seen": "2026-08-16T18:51:04Z",
      "link_rate": 70,
      "source_page_rate": 81,
      "source_domain_rate": 65,
      "source_spam_score": 0,
      "target_spam_score": 0,
      "source_type": "blog",
      "source_country": "DE",
      "source_language": "de",
      "source_page_title": "The best SEO tools in 2026",
      "source_page_status_code": 200,
      "source_page_size_bytes": 28259,
      "source_page_internal_links": 31,
      "source_page_external_links": 4,
      "target_status_code": 200,
      "target_redirect_url": null
    }
  ]
}

Response Fields Reference

Envelope

FieldTypeDescription
successbooleantrue when the request succeeded
cachedbooleantrue when served from cache, at the reduced rate
costnumberWhat this request cost, in USD
typestringThe report returned
targetstringThe normalized target
scopestringThe scope applied
totalintegerApproximate number of matching rows
countintegerRows in this response
limitintegerThe limit applied
offsetintegerThe offset applied
next_cursorstring | nullPass as cursor for the next page
resultsarrayThe rows, for every report except summary
resultobjectThe single metric block, for summary
FieldTypeDescription
source_urlstringPage containing the link
source_domainstringHost of the linking page, without www.
target_urlstringURL that was linked to
target_domainstringHost that was linked to
source_tldstringTLD of the linking domain
anchor_textstringVisible clickable text
anchor_typestringexact, branded, naked_url, generic, partial, image, empty or other
image_urlstring | nullSource of the linked image, for image links
image_altstring | nullalt text of the linked image
context_beforestring | nullText immediately before the anchor
context_afterstring | nullText immediately after the anchor
link_typestringtext, image, redirect, canonical, alternate, meta, feed, form or other
link_positionstringcontent, nav, header, footer or sidebar
is_dofollowbooleanWhether the link passes authority
is_ugcbooleanMarked as user-generated
is_sponsoredbooleanMarked as paid
rel_attributesarrayrel values present on the anchor
via_redirectbooleanReached through a redirect or canonical
identical_links_countintegerCopies of this same link on the source page
is_newbooleanAppeared in the most recent crawl window
is_livebooleanLink is still in place
is_brokenbooleanPoints at a page returning 4xx or 5xx
first_seenstring | nullRFC3339 timestamp of first discovery
last_seenstring | nullRFC3339 timestamp of most recent sighting
link_ratenumberAuthority passed by this link, 0–100
source_page_ratenumberAuthority of the linking page, 0–100
source_domain_ratenumberAuthority of the linking domain, 0–100
source_spam_scoreintegerSpam likelihood of the source, 0–100
target_spam_scoreinteger | nullSpam likelihood of the linked page
source_typestringblog, forum, news, business, wiki, ecommerce or other
source_countrystring | nullISO 3166-1 alpha-2 country of the linking server
source_languagestring | nullDetected language of the linking page
source_page_titlestring | nullTitle of the linking page
source_page_status_codeinteger | nullHTTP status of the linking page
source_page_size_bytesinteger | nullByte size of the linking page
source_page_internal_linksinteger | nullInternal links on the linking page
source_page_external_linksinteger | nullExternal links on the linking page
target_status_codeinteger | nullHTTP status of the linked page
target_redirect_urlstring | nullWhere the linked page redirects

A null here means unknown, not zero — a page the crawler has not fetched has no status code, and treating that as 0 would be misleading.

Summary and history metrics

FieldTypeDescription
semust_ratenumberAuthority of the target, 0–100
total_backlinksintegerAll backlinks
dofollow_backlinksintegerBacklinks passing authority
nofollow_backlinksintegerBacklinks marked nofollow
broken_backlinksintegerBacklinks pointing at broken pages
broken_pagesintegerTarget pages returning 4xx or 5xx
avg_spam_scoreintegerAverage spam score across backlinks
referring_domainsintegerUnique domains linking to the target
referring_domains_dofollowintegerDomains linking exclusively with dofollow links
referring_domains_nofollowintegerDomains with at least one nofollow link
referring_root_domainsintegerUnique root domains
referring_ipsintegerUnique IP addresses
referring_subnetsintegerUnique subnets
referring_pagesintegerUnique pages linking to the target
text_links_countintegerText links
image_links_countintegerImage links
redirect_links_countintegerRedirect links
internal_links_countintegerInternal links across the target
outgoing_links_countintegerOutgoing links from the target
links_by_tldobjectLink count by TLD
links_by_typeobjectLink count by link type
links_by_attributeobjectLink count by rel attribute
links_by_positionobjectLink count by position on the page
links_by_countryobjectLink count by country
links_by_source_typeobjectLink count by kind of site

referring_domains_dofollow

referring_domains_nofollow counts every domain with at least one nofollow link, so referring_domains_dofollow is the number of domains linking only with dofollow links — not the number with at least one.

history adds date, new_backlinks, lost_backlinks, new_referring_domains and lost_referring_domains to each point. The links_by_* maps are empty unless include_breakdowns is true.

Error Codes

StatusCodeDescription
400INVALID_REQUESTBody is malformed, or a parameter does not apply to this type
400TARGET_REQUIREDThe target field is missing
400INVALID_TARGETtarget is not a valid domain or URL
400INVALID_TYPEUnknown type
400INVALID_FILTERUnknown field, wrong operator for the field, or too many conditions
400INVALID_ORDER_BYUnknown sort field, or more than 3 rules
400INVALID_DATE_RANGEdate_from is after date_to, or the dates are unparseable
400INVALID_CURSORThe cursor is unknown, expired, or not valid for this request
401INVALID_CREDENTIALSUsername or password is wrong
402INSUFFICIENT_CREDITSNot enough balance for this request
403SERVICE_NOT_ENABLEDBacklinks is not enabled for your account
403IP_NOT_WHITELISTEDYour IP address is not whitelisted
409REQUEST_IN_PROGRESSThe same idempotency_key is already running
413REQUEST_TOO_LARGERequest body exceeds 64 KB
429RATE_LIMIT_EXCEEDEDToo many requests
502REQUEST_FAILEDThe request could not be completed
504TIMEOUTThe request timed out

Every 4xx above is checked before anything is charged, so a rejected request costs nothing.

Failures carry a request_id. Quote it when contacting support and we can find the exact cause.

{
  "error": "invalid filter: unknown field \"domain_rating\"",
  "code": "INVALID_FILTER"
}

Credits & Rate Limits

Credits

Pricing is a base fee per request plus a fee for each row returned:

cost = $0.0264 + (rows / 1000) x $0.0396
Rows returnedCost
0$0.026400
1 (summary)$0.026440
100$0.030360
500$0.046200
1000 (maximum)$0.066000

A request that matches nothing still costs the base fee. Requesting fewer rows costs less, so set limit to what you actually need.

history and timeseries bill one row per period in the range.

Caching

Identical requests are cached and served at a flat $0.005, with "cached": true in the response. Most reports cache for 24 hours; history caches for 7 days because the underlying data only changes monthly.

Rate Limits

Rate limits are per API user and are set on your account. Exceeding them returns 429 RATE_LIMIT_EXCEEDED. See Rate Limits for details.

Last updated: 2026-08-29