Page audit
Before you look at rankings, look at the page. This endpoint fetches a URL the way a browser would and returns everything an on-page review needs: a score built from twelve rules you can read, the elements behind each rule, and the timing and crawl signals that decide whether Google indexes the page at all. It runs on our own servers, so it costs half a credit and answers in a couple of seconds.
Audit a URL
Returns the audit of one page. The score starts at 100 and loses the weight of every check that fails, so two pages with the same score have the same problems. warnings lists things that do not change the score but a human should know, like a noindex or a canonical pointing elsewhere.
Costs 0.6 credits per call. Pages are read up to 2 MB; larger ones are analysed on their first 2 MB and say so.
Required attributes
- Name
url- Type
- string
- Description
The page to audit.
https://is assumed when you leave the scheme out, andhttp://is upgraded. Private and internal addresses are refused.
Checks and weights
| Check | Weight |
|---|---|
| Title present, 10 to 60 characters | 12 |
| Meta description, 50 to 160 characters | 12 |
| Exactly one H1 | 10 |
| Served over HTTPS | 10 |
| Every image has alt text | 10 |
| Canonical URL declared | 8 |
| Open Graph tags present | 8 |
| Valid JSON-LD structured data | 8 |
| HTML under 200 KB | 6 |
| Response under 1500 ms | 6 |
lang attribute on <html> | 5 |
| Twitter Card tags present | 5 |
Response fields
- Name
score- Type
- integer
- Description
0 to 100. Each failed check subtracts its weight.
- Name
indexable- Type
- boolean
- Description
falsewhen the page answers an error, carriesnoindex, or robots.txt disallows its path.
- Name
checks[]- Type
- array
- Description
One entry per rule with
id,label,weight,passedand adetailthat says what was found.
- Name
warnings[]- Type
- array
- Description
Findings outside the score: noindex, robots.txt blocks, missing viewport, thin content, canonical pointing to another URL.
- Name
page- Type
- object
- Description
Title and description with their lengths, canonical, robots meta,
lang, viewport, word count, headings by level, image and link counts with examples, Open Graph and Twitter tags, JSON-LD types, hreflang alternates.
- Name
performance- Type
- object
- Description
Time to first byte, total time, HTML size, compression, server header, cache control and how many scripts, stylesheets, iframes and images the HTML references. Measured for the document only, without rendering.
- Name
robots_txt- Type
- object
- Description
Whether robots.txt exists, the sitemaps it declares, and whether it disallows this path for all crawlers.
Request
curl -X POST https://suvjexogmfpvxjcktvuk.supabase.co/functions/v1/api/v1/pages/audit \
-H "Authorization: Bearer $PENGU_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://mailchimp.com/"}'
Response
{
"data": {
"url": "https://mailchimp.com/",
"final_url": "https://mailchimp.com/",
"status": 200,
"fetched_at": "2026-09-10T07:56:59.897Z",
"score": 72,
"indexable": true,
"checks": [
{ "id": "title", "label": "Title present, 10 to 60 characters", "weight": 12, "passed": true, "detail": "41 characters" },
{ "id": "meta_description", "label": "Meta description, 50 to 160 characters", "weight": 12, "passed": false, "detail": "216 characters" },
{ "id": "single_h1", "label": "Exactly one H1", "weight": 10, "passed": true, "detail": "1 H1 found" },
{ "id": "image_alt", "label": "Every image has alt text", "weight": 10, "passed": false, "detail": "2 of 94 images without alt" },
{ "id": "html_size", "label": "HTML under 200 KB", "weight": 6, "passed": false, "detail": "487.3 KB" },
// ...
],
"warnings": [],
"page": {
"title": "Email Marketing Platform | Mailchimp",
"title_length": 41,
"meta_description_length": 216,
"canonical": "https://mailchimp.com/",
"robots_meta": "index,follow,archive",
"lang": "en",
"word_count": 2395,
"headings": {
"h1": ["Email and SMS marketing without the learning curve"],
"h2": ["Most popular", "Recommended for your business", "..."],
"counts": { "h1": 1, "h2": 13, "h3": 16, "h4": 28, "h5": 0, "h6": 0 }
},
"images": { "total": 94, "missing_alt": 2, "lazy_loaded": 61, "missing_alt_examples": ["..."] },
"links": { "internal": 212, "external": 9, "nofollow": 0, "external_examples": ["..."] },
"structured_data": ["WebPage"],
"hreflang_alternates": 12
},
"performance": {
"ttfb_ms": 212,
"total_ms": 640,
"html_size_kb": 487.3,
"compression": "br",
"resources": { "scripts": 31, "stylesheets": 4, "iframes": 0, "images": 94 }
},
"robots_txt": { "present": true, "sitemaps": ["https://mailchimp.com/sitemap.xml"], "disallows_page": false }
},
"meta": {
"credits_charged": 0.5,
"credits_remaining": 483,
"request_id": "6c1d0f7a-2f3b-4f0e-9d21-8a5c4b0e1f22"
}
}
What it is good for
- First call of any audit. Run it on the home page and the three pages that matter most before spending credits on rankings. Most quick wins are here.
- Batch checks from an agent. Ask Claude to list a site's URLs with the sitemap endpoint below, audit the newest fifty and table the scores. At half a credit a page, a hundred pages cost fifty credits.
- Before and after. Audit, fix, audit again. The checks are deterministic, so a score change means a real change.
Pages are fetched from our servers in Europe. A site that redirects visitors by location will do so here too, and final_url says where you landed; pass the exact localised URL when it matters, for example mailchimp.com/en-us/ instead of mailchimp.com.
It reads the HTML as served, without running JavaScript. A page whose title or content only exists after client-side rendering will look thin here, which is itself worth knowing: Google renders JavaScript, but later and less often.
Sitemap URLs
The URLs a site declares in its sitemaps, with their lastmod. Sitemaps are found through robots.txt and the usual locations (/sitemap.xml, /sitemap_index.xml), sitemap indexes are followed, and gzipped files are read. Up to 500 URLs come back, newest first when the site dates them.
Costs 0.6 credits per call.
Required attributes
- Name
site- Type
- string
- Description
A domain such as
hubspot.com, a site URL, or a direct sitemap URL when you already know it.
Optional attributes
- Name
limit- Type
- integer
- Description
URLs to return, 10 to 500. Default 100.
Response fields
- Name
sitemaps- Type
- array
- Description
The sitemap files that were read, in order.
- Name
truncated- Type
- boolean
- Description
truewhen the site declares more URLs or child sitemaps than were read. Large sites usually do.
- Name
urls[]- Type
- array
- Description
urlandlastmod(ISO date ornull).
Request
curl -X POST https://suvjexogmfpvxjcktvuk.supabase.co/functions/v1/api/v1/pages/sitemap \
-H "Authorization: Bearer $PENGU_API_KEY" \
-H "Content-Type: application/json" \
-d '{"site": "hubspot.com", "limit": 50}'
Response
{
"data": {
"site": "https://www.hubspot.com",
"sitemaps": [
"https://www.hubspot.com/sitemap.xml",
"https://www.hubspot.com/sitemap-products.xml"
],
"count": 50,
"truncated": true,
"urls": [
{ "url": "https://www.hubspot.com/products/crm", "lastmod": "2026-09-08" },
{ "url": "https://www.hubspot.com/products/marketing", "lastmod": "2026-09-08" },
// ...
]
},
"meta": {
"credits_charged": 0.5,
"credits_remaining": 482.5,
"request_id": "4a7f2c19-8e3d-4b6a-9f10-2c5d7e8f9a01"
}
}
