RankParse

Page SEO

Real-time SEO audit of any public URL, covering title, meta, canonical, Open Graph, hreflang, headings, images and links.

GET/v1/page-seo3 credits (refunded on failure)API key

Fetches a public URL at request time and returns a structured on-page SEO audit. Use it to check a single page's title and description lengths, canonical, robots directives, social tags and link counts. This is a live fetch, not Common Crawl data, so it reflects the page as it is right now.

Request

Parameters

NameTypeRequiredDefaultDescription
urlstringYesnoneFull http:// or https:// URL of the page to analyze. See URL rules.

Example

curl "https://api.rankparse.com/v1/page-seo?url=https://stripe.com/about" \
  -H "X-API-Key: rp_your_key"
import requests

resp = requests.get(
    "https://api.rankparse.com/v1/page-seo",
    params={"url": "https://stripe.com/about"},
    headers={"X-API-Key": "rp_your_key"},
    timeout=30,
)
resp.raise_for_status()
audit = resp.json()["data"]
print(audit["title"]["text"], audit["title"]["optimal"])
const res = await fetch(
  "https://api.rankparse.com/v1/page-seo?" +
    new URLSearchParams({ url: "https://stripe.com/about" }),
  { headers: { "X-API-Key": process.env.RANKPARSE_API_KEY } }
);
if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
const { data } = await res.json();
console.log(data.title.text, data.title.optimal);

Response

{
  "url": "https://stripe.com/about",
  "data": {
    "url": "https://stripe.com/about",
    "final_url": "https://stripe.com/about",
    "status_code": 200,
    "response_time_ms": 312,
    "title": { "text": "About Us - Example", "length": 18, "optimal": false },
    "description": { "text": "Learn about Example Inc.", "length": 24, "optimal": false },
    "canonical": { "url": "https://stripe.com/about", "self_referential": true },
    "robots": { "index": true, "follow": true, "raw": "index,follow" },
    "viewport": "width=device-width, initial-scale=1",
    "language": { "primary": "en", "tag": "en-US", "source": "html_lang" },
    "hreflang": [
      { "lang": "en", "url": "https://stripe.com/about" },
      { "lang": "fr", "url": "https://fr.stripe.com/about" }
    ],
    "headings": {
      "h1": ["About Us"],
      "h2": ["Our Story", "Our Team"],
      "h3_count": 4
    },
    "og": {
      "title": "About Us - Example",
      "description": "Learn about Example Inc.",
      "image": "https://stripe.com/og-image.jpg",
      "type": "website",
      "url": "https://stripe.com/about"
    },
    "twitter": {
      "card": "summary_large_image",
      "title": "About Us - Example"
    },
    "json_ld": [{ "@type": "Organization", "name": "Example Inc." }],
    "images": { "total": 8, "missing_alt": 2 },
    "links": { "internal": 24, "external": 3 },
    "word_count": 412,
    "favicon": "https://stripe.com/favicon.ico"
  },
  "credits_used": 3,
  "credits_remaining": 997
}

Response fields

FieldTypeDescription
urlstringThe URL you sent (top level and inside data).
final_urlstringThe URL after following redirects.
status_codeintegerHTTP status the target returned. The API still answers 200 and bills you when the target returns 404 or 500, so check this field.
response_time_msintegerTime taken to fetch the page, including redirects.
titleobjecttext (string or null), length (characters), optimal (true when length is 30 to 60).
descriptionobjectMeta description: text (string or null), length, optimal (true when length is 120 to 160).
canonicalobjecturl of the canonical link, and self_referential: true when it equals final_url or the URL you sent, null when no canonical exists.
robotsobjectFrom the robots meta tag: index and follow (both true unless noindex or nofollow appears), and the lowercased raw value (null when no tag).
viewportstring or nullContent of the viewport meta tag.
languageobjectprimary (e.g. en), full tag (e.g. en-US) and source: html_lang, content_language_header or meta_http_equiv. All null when none is found.
hreflangarray{ lang, url } for each rel="alternate" link carrying an hreflang.
headingsobjecth1 (all H1 texts), h2 (first 10 H2 texts) and h3_count (number of H3 elements).
ogobjectOpen Graph tags keyed by the name after og:, with colon-separated parts camel-cased (og:image:width becomes imageWidth). Empty object when none.
twitterobjectTwitter card tags keyed by the name after twitter:. Empty object when none.
json_ldarrayParsed JSON-LD objects found on the page. Malformed blocks are skipped. For flattened entities and per-block diagnostics use Schema Markup.
imagesobjecttotal image tags and missing_alt (images with a missing or empty alt).
linksobjectinternal and external anchor counts, split by whether the link host matches the final URL's host.
word_countintegerWords of visible text after removing scripts, styles and tags.
faviconstringAbsolute URL of the declared icon, or /favicon.ico on the final host when none is declared (existence is not checked).
credits_usedintegerAlways 3 on success.
credits_remainingintegerBalance after the charge.

Behavior and limits

URL rules

  • Only http and https are accepted. No credentials in the URL, no leading or trailing whitespace, and no fragment: any # in the URL is rejected with invalid_url.
  • Hosts must be public. localhost, *.local, *.internal, *.home.arpa, private and reserved IPv4 or IPv6 ranges, and hosts without a dot are rejected with private_ip. Every redirect hop is re-validated, so a public URL cannot redirect you into a private address.
  • Up to 5 redirects are followed.

Fetch limits

  • Timeout is 8 seconds for the whole fetch.
  • Only the first 2 MB of a response is accepted. Larger responses fail with response_too_large.
  • The request is sent with the user agent Mozilla/5.0 (compatible; RankParse/1.0; +https://rankparse.com). Sites that block unknown bots may return an error page; the audit then describes that page.
  • Pages are parsed from the raw HTML the server returns. Content rendered by client-side JavaScript is not seen.

Billing

  • Costs 3 credits. If the call fails after being charged (any non-2xx response, such as 503 fetch_failed), the 3 credits are refunded automatically. Requests with a malformed or private URL are rejected before billing.
  • Calls count against the standard 60 requests per minute limit. See Rate limiting.

Errors

StatusCodeWhen
400invalid_urlMissing, malformed or non-http(s) URL; credentials, whitespace or a fragment in the URL.
400private_ipHost is private, reserved or local.
400response_too_largeThe page body exceeded 2 MB.
401invalid_api_keyMissing, invalid or revoked key.
402insufficient_creditsBalance below 3 credits.
402spend_cap_reachedYour monthly spend cap was reached.
429rate_limitedMore than 60 requests per minute.
503fetch_failedThe target was unreachable, refused the connection, or redirected too many times.
503timeoutThe target did not respond within 8 seconds.

Error bodies look like { "error": "Service Unavailable", "code": "fetch_failed" }. See Errors for the shared format.

MCP tool: get_page_seo.

On this page