SEO Page Audit: Titles, Meta, Headings, Links | $1/1K
Pricing
from $1.00 / 1,000 results
SEO Page Audit: Titles, Meta, Headings, Links | $1/1K
$1 per 1,000 results, platform usage included. On-page SEO audit for any URL: status and redirects, title, meta description, headings, canonical, links, images, social tags and structured data, with a list of issues and a score. Plain HTTP, no login.
Pricing
from $1.00 / 1,000 results
Rating
0.0
(0)
Developer
One Dollar Store
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Share
SEO Page Audit: titles, meta tags, headings, links and issues for any URL
$1 per 1,000 pages. Platform usage included. No rental, no minimum.
Give it page addresses and get one row per page with the on-page SEO facts and a list of issues: HTTP status and redirects, title, meta description, canonical, robots tags, headings, word count, links, images without an alt attribute, Open Graph and Twitter tags, structured data types, hreflang and a score. It reads the page as plain HTML over HTTP, with no browser.
New to Apify? [Create a free account](https://www.apify.com?fpr=ymnoit) (referral link). Runs from a free plan account return the first 10 results; any paid plan returns everything you ask for, up to your limit.What it costs
| Pages | Price |
|---|---|
| 1,000 | $1.00 |
| 10,000 | $10.00 |
| 100,000 | $100.00 |
Plus $0.001 per run. One flat price, platform usage included, so there is no separate compute or proxy bill. A weekly audit of 500 pages costs about $0.50, or about $2 a month.
Why use it
- One flat price. The bill follows the number of pages and nothing else. There is no browser or proxy behind it.
- Facts and verdicts together. Every row has the raw values (title text and length, heading list, link counts) and an
issueslist with a code, a severity and a plain message, so you can filter ontitle_missingorimages_missing_altin a spreadsheet. - Status codes are results too. A page that answers 404 or 500 still gives a row with its status, so you can run a list of URLs through it to find broken pages. The redirect chain is included.
- Built for lists. Run hundreds of URLs in one go, schedule it, and compare
scoreandissueCountbetween runs.
Quick start
- Open the actor, add one page address per line, press Start.
- Or paste this input:
{ "urls": ["https://www.python.org/", "https://docs.apify.com/platform/actors"], "maxItems": 10 }
- Download the results as JSON, CSV or Excel, or read them through the API.
Use it from code
curl -X POST "https://api.apify.com/v2/acts/one_dollar_store~seo-page-audit-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"urls": ["https://www.python.org/"], "maxItems": 10}'
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("one_dollar_store/seo-page-audit-scraper").call(run_input={"urls": ["https://www.python.org/"], "maxItems": 10})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["finalUrl"], item["score"], [i["code"] for i in item["issues"]])
Use it from an AI assistant
Claude, ChatGPT, Cursor and other assistants can call this actor through Apify's MCP server. Add it with this server address:
https://mcp.apify.com?tools=one_dollar_store/seo-page-audit-scraper
Then ask, for example: "Audit these 30 product pages and list the ones with a missing meta description or more than one H1."
Switching from another SEO audit actor
Most SEO audit actors take a start URL or a list of URLs. Here it is urls (a list, one row per address) and maxItems. The core fields are finalUrl, statusCode, title, metaDescription, h1, canonicalUrl, wordCount, issues and score. The actor audits the pages you list. It does not crawl a whole site.
Input
| Field | Type | Default | What it does |
|---|---|---|---|
urls | list of text | none | Page addresses to audit, one per line. A bare domain or a full address. Each address gives one row. |
includeLinks | true or false | false | Add a links list to each row (up to 500 links with address, text, internal or external, nofollow). The link counts are always included. |
maxItems | number | 100 | The run stops after this many results. Minimum 10. |
A bare domain is tried over https first, then http. The same address listed twice is audited once.
Output fields
| Field | Meaning |
|---|---|
url, finalUrl, statusCode | The address, the page after redirects, and the HTTP status. |
redirectCount, redirectChain | Redirect hops with status and address, up to 5. |
responseTimeMs, htmlBytes, contentType, server | Time the server took to answer (measured from Apify's servers), size read, content type and Server header. |
indexable | false for error pages and pages marked noindex in the robots meta tag or X-Robots-Tag header. |
title, titleLength, metaDescription, metaDescriptionLength | Title and meta description with their lengths. |
canonicalUrl, robotsMeta, xRobotsTag, lang, charset, viewport | Canonical link, robots directives, language, character set, viewport tag. |
h1, headingCounts, headings | H1 texts, count per heading level, and the outline (first 60). |
wordCount | Words of visible text in the HTML. |
imageCount, imagesMissingAlt, imagesEmptyAlt | Images, those with no alt attribute, and those with an empty one (the standard mark for a decorative image, counted but not flagged). |
internalLinks, externalLinks, nofollowLinks, linksWithoutText, mixedContentCount | Link counts, and http resources on an https page. |
openGraph, twitterCard, jsonLdTypes, hreflang, favicon | Social tags, structured data types, language alternates, favicon link. |
links | Only with includeLinks. |
score | 100 minus 15 per error, 5 per warning, 1 per notice, never below 0. |
issueCount, issues | Failed checks: code, severity (error, warning, notice) and message. |
scrapedAt | Time of the audit in UTC. |
Checks
| Code | Severity | Raised when |
|---|---|---|
http_error | error | The status is 400 or higher. |
certificate_invalid | error | The HTTPS certificate failed the check (the page is still read). |
not_html | error | The address returns a file, not an HTML page. |
title_missing, h1_missing | error | No title tag, or no H1. |
title_short, title_long | warning | Title under 30 or over 60 characters. |
meta_description_missing, meta_description_long | warning | No meta description, or over 160 characters. |
h1_multiple, h1_empty | warning | More than one H1, or an empty one. |
canonical_missing | warning | No canonical link. |
noindex | warning | Robots meta tag or X-Robots-Tag says noindex. |
viewport_missing | warning | No viewport meta tag. |
not_https | warning | The final page is served over http. |
mixed_content | warning | Resources load over http on an https page. |
images_missing_alt | warning | Images with no alt attribute. |
thin_content | warning | Under 300 words of text in the HTML. |
redirect_chain_long, slow_response | warning | Three or more redirects, or an answer slower than 3 seconds. |
meta_description_short, heading_level_skipped, canonical_other_page, lang_missing, open_graph_missing, twitter_card_missing, structured_data_missing, favicon_missing, redirected, html_large | notice | Smaller points: a description under 70 characters, a skipped heading level, a canonical pointing to another page, no lang, no Open Graph or Twitter tags, no JSON-LD, no favicon link, one or two redirects, or HTML over 1 MB. |
The length limits are common rules of thumb, not rules set by any search engine.
Sample results
Real rows from a test run on 9 October 2026. A few fields (url, headings, headingCounts, server, contentType, charset, viewport, favicon, hreflang, twitterCard, scrapedAt) are left out here for space.
[{"finalUrl": "https://www.python.org/", "statusCode": 200, "responseTimeMs": 106, "htmlBytes": 52308, "indexable": true, "title": "Welcome to Python.org", "titleLength": 21, "metaDescription": "The official home of the Python Programming Language", "metaDescriptionLength": 52, "lang": "en", "h1": ["Functions Defined", "All the Flow You’d Expect", "Compound Data Types", "Intuitive Interpretation", "Quick & Easy to Learn"], "wordCount": 971, "imageCount": 1, "imagesMissingAlt": 0, "imagesEmptyAlt": 0, "internalLinks": 126, "externalLinks": 78, "nofollowLinks": 0, "linksWithoutText": 0, "openGraph": {"title": "Welcome to Python.org", "description": "The official home of the Python Programming Language", "image": "https://www.python.org/static/opengraph-icon-200x200.png", "type": "website", "url": "https://www.python.org/", "site_name": "Python.org"}, "jsonLdTypes": ["WebSite"], "score": 83, "issueCount": 5, "issues": [{"code": "title_short", "severity": "warning", "message": "Title is 21 characters; 30 to 60 is a common target."}, {"code": "meta_description_short", "severity": "notice", "message": "Meta description is 52 characters; 70 to 160 is a common target."}, {"code": "h1_multiple", "severity": "warning", "message": "5 H1 headings."}, {"code": "canonical_missing", "severity": "warning", "message": "No canonical link."}, {"code": "twitter_card_missing", "severity": "notice", "message": "No Twitter card tag."}]},{"finalUrl": "https://www.gnu.org/philosophy/free-sw.html", "statusCode": 200, "responseTimeMs": 703, "htmlBytes": 50511, "indexable": true, "title": "What is Free Software? - GNU Project - Free Software Foundation", "titleLength": 63, "metaDescription": "Since 1983, developing the free Unix style operating system GNU, so that computer users can have the freedom to share and improve the software they use.", "metaDescriptionLength": 152, "lang": "en", "h1": [], "wordCount": 4167, "imageCount": 5, "imagesMissingAlt": 0, "imagesEmptyAlt": 0, "internalLinks": 103, "externalLinks": 14, "nofollowLinks": 1, "linksWithoutText": 0, "jsonLdTypes": [], "score": 72, "issueCount": 6, "issues": [{"code": "title_long", "severity": "warning", "message": "Title is 63 characters; search results often cut titles near 60."}, {"code": "h1_missing", "severity": "error", "message": "No H1 heading."}, {"code": "canonical_missing", "severity": "warning", "message": "No canonical link."}, {"code": "open_graph_missing", "severity": "notice", "message": "No Open Graph title or image for social sharing."}, {"code": "twitter_card_missing", "severity": "notice", "message": "No Twitter card tag."}, {"code": "structured_data_missing", "severity": "notice", "message": "No JSON-LD structured data."}]}]
Limits
- It audits the pages you list. It does not crawl a site, check every link on a page for broken targets, or measure page speed in a browser.
responseTimeMsis only how long the server took to deliver the HTML, measured from Apify's servers. - No JavaScript is run. The audit sees the HTML the server sends. A title, heading or link that scripts add later is not seen, so a single page app can look emptier than it does in a browser.
- robots.txt is honoured. A page it does not allow gives no row and is listed in the run summary. If robots.txt cannot be read because of a server error, the page is skipped too.
- Sites that block cloud servers or show a bot check page are skipped. The actor does not try to get past a check.
- A row for any HTTP answer. Pages that answer 404, 500 and similar give a row with that status. Addresses that cannot be reached at all (no such host, timeout) give no row and are listed in the run summary.
- Only the first 2 MB of a page is read. Redirects are followed, up to 5.
- The rules are rules of thumb. Title and description lengths, the word count for thin content and the score are common guidelines, not what any search engine requires. Use
issuesas a checklist, not a verdict. - Free plan runs return the first 10 results.
- Every run writes a
RUN_SUMMARYrecord with counts and the list of skipped addresses and why.
FAQ
How much does it cost to audit 10,000 pages? $10, plus $0.001 for each run.
Do I pay for compute or proxy on top? No. Platform usage is included in the $1 per 1,000 price. The actor uses no proxy.
Can I find broken pages with it?
Yes. Run a list of URLs and filter on statusCode of 400 or more, or on the http_error issue. It checks the pages you list, not the links inside them.
Does it crawl my whole site? No. Give it the URLs, for example from your sitemap. That keeps the price per page fixed and the run predictable.
How is the score worked out? It starts at 100 and loses 15 points per error, 5 per warning and 1 per notice. The full list of checks is in the Checks table above.
Is it legal? The actor reads public pages that a site sends to any visitor, with no login, and respects robots.txt. Audit your own sites and other public pages in line with each site's terms and the law where you live.
Is this an official product of any search engine or SEO tool? No. It is an independent tool and is not affiliated with or endorsed by any search engine or SEO company.
Do I need an Apify account? Yes. Actors run from an Apify account, and a free account is enough to start: it includes $5 of platform usage every month. You can sign up here. This is a referral link and it costs you nothing.
Is there a limit on the free plan? Yes. A run started from a free plan account delivers the first 10 results, then ends with a message and a link to the plans. Any paid plan returns everything you ask for, up to your own limit. The price per result is the same on every plan.
More from The One Dollar Store
Every actor here costs $1 per 1,000 results, platform usage included. See the whole store: https://apify.com/one_dollar_store
Website tools
- Website Technology Detector: Frameworks, CMS, analytics and ad tags on any site.
- Website to Markdown Converter: Clean Markdown text from any web page.
- Website Contact Scraper: Emails, phones and social links from company sites.
- PDF Text Extractor: Text and page data from PDF links.
Changelog
- October 2026: first release.