Seo Heading Structure Checker avatar

Seo Heading Structure Checker

Pricing

$0.01 / actor start

Go to Apify Store
Seo Heading Structure Checker

Seo Heading Structure Checker

Pricing

$0.01 / actor start

Rating

0.0

(0)

Developer

Eichan Jolly

Eichan Jolly

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Security

Limited permissions

Share

Checks H1–H6 heading order on 1–5 user-supplied public HTML pages. Designed for SEO analysts, site owners, and content editors doing a quick structural audit.

What it does

Fetches each supplied page (including a same-host redirect), honors robots.txt, extracts headings in document order, and reports missing/multiple H1s, an initial heading other than H1, skipped downward heading levels, and empty headings. Every input URL yields exactly one dataset item, even if the fetch fails. Text within headings is whitespace-normalized. The Actor does not inspect rendered JavaScript content.

Input example

{"urls": ["https://example.com/"]}

Input urls is required, with 1–5 HTTP(S) URLs. Prefill uses one URL. No login, cookies, search results, search scraping, pagination, or domain discovery.

Output example (illustrative)

{
"url": "https://example.com/article",
"headings": [{"level": "H1", "text": "Guide"}, {"level": "H3", "text": "Details"}],
"h1Count": 1,
"skippedLevels": [{"from": "H1", "to": "H3"}],
"issues": ["Heading level jumps from H1 to H3."],
"status": "issues_found",
"error": null
}

Fields are always present: url (string), headings (array of {level,text}), h1Count (integer), skippedLevels (array of {from,to}), issues (array of strings), status (ok, issues_found, or error), error (string or null). When status=error, headings are empty and the plain-language cause is in error.

Execution and dataset storage

  • Apify cloud: configure APIFY_TOKEN, ACTOR_DEFAULT_KEY_VALUE_STORE_ID, and ACTOR_DEFAULT_DATASET_ID (the platform supplies these). The code reads INPUT via the Apify REST API and appends records to the default dataset. No Apify SDK is imported.
  • Locally: set ACTOR_INPUT_JSON to a JSON string, or create storage/key_value_stores/default/INPUT.json; run python src/main.py. Dataset items are written as numbered JSON files under storage/datasets/default/ (or APIFY_LOCAL_STORAGE_DIR/datasets/default/).
  • Docker: docker build -t seo-heading-structure-checker .; to run with an input JSON environment variable, use docker run --rm -e ACTOR_INPUT_JSON='{"urls":["https://example.com/"]}' seo-heading-structure-checker. Local output stays in the container unless storage is volume-mounted.

Limits and safeguards

  • At most 5 pages per run, 1 MB downloaded per page, and 150 headings returned per page (the H1 count and checks still consider all parsed headings).
  • Maximum 3 redirects, all same hostname; HTTPS-to-HTTP downgrade is refused. Responses have an 8-second timeout each. robots.txt lookup is capped at 250 KB and checked first; HTTP robots errors fail closed except 404/410 (treated as absent). Python's urllib.robotparser supports a subset of modern robots directives.
  • Only HTTP(S) public hostnames/IPs. Local/private/reserved addresses are refused by default. DNS is checked before requests but DNS rebinding is not cryptographically prevented. No JavaScript rendering, CSS layout/visibility analysis, schema parsing, or WCAG compliance certification.
  • An ACTOR_TEST_ALLOW_LOOPBACK=1 test-only environment override permits localhost fixtures; do not configure this in production.
  • Parsing may miss headings introduced by client-side JavaScript or atypical malformed HTML. No headless browser or dependencies.

Declared category recommendations (not Store-configured)

SEO tools · Marketing (2 categories).

Suggested pricing (not configured)

Pay per run: USD $0.01 per completed run (up to five URLs). This is a recommendation only; no billing has been configured or published.

Reproducible verification

From this folder:

python tests/run_smoke.py
python -m unittest discover -s tests -v

tests/run_smoke.py runs python src/main.py as a subprocess with a valid ACTOR_INPUT_JSON and a local HTTP fixture server. It writes the actual stdout, dataset records, and input used to tests/evidence/. The fixture uses the test-only loopback override. tests/test_actor.py also uses script-mode subprocesses; it does not import the Actor for its behavioral tests.