Website Release QA: SEO, Links & Screenshots avatar

Website Release QA: SEO, Links & Screenshots

Pricing

from $50.00 / 1,000 page auditeds

Go to Apify Store
Website Release QA: SEO, Links & Screenshots

Website Release QA: SEO, Links & Screenshots

Check 1–10 public pages before launch. Render in Chromium, capture screenshots, test redirects and internal links, and verify SEO, indexability, image-alt, landmark, and form-label rules with deterministic pass, fail, or unknown evidence.

Pricing

from $50.00 / 1,000 page auditeds

Rating

0.0

(0)

Developer

Sassy Labs

Sassy Labs

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Website Release QA

Website Release QA is a deterministic, browser-rendered website audit tool for pre-launch checks, releases, campaigns, migrations, and client handoffs. Add 1–10 public URLs and get screenshots plus explicit pass, fail, or unknown evidence for delivery, redirects, internal links, SEO metadata, indexability, image alt coverage, page landmarks, and form labels.

Use it before a production release, landing-page campaign, domain migration, or client handoff when you need a repeatable release receipt rather than a generic score. The Actor never logs in or submits forms, does not intentionally perform write actions, and does not ask a language model to interpret the result. Browser routing blocks non-read-only HTTP methods; the Actor issues GET navigations and bounded HEAD/GET link probes, so target sites must treat those methods as read-only.

Current package release: 0.2.0. The Apify Actor definition uses the corresponding major/minor version 0.2.

Live Store listing: https://apify.com/sassy_labs/website-release-qa

Checks

For each page, release 0.2.0 checks:

  • final HTTP status and redirect count;
  • document title and meta-description length;
  • canonical URL presence, validity, and optional same-origin enforcement;
  • H1 count;
  • meta robots and X-Robots-Tag noindex directives;
  • bounded unique same-origin links;
  • image alt attribute coverage, including explicit empty decorative alts;
  • a main or role=main landmark;
  • accessible names for non-hidden controls inside forms; and
  • a Chromium viewport screenshot saved to the run's key-value store.

The first dataset record is the run-level overview. Every subsequent item is a detailed finding. The overview dataset view is optimized for scanning status, severity, category, observed evidence, and screenshot links.

Example input

{
"urls": [
"https://example.com/",
"https://example.com/about"
],
"maxRedirects": 5,
"maxInternalLinksPerPage": 20,
"minTitleChars": 10,
"maxTitleChars": 60,
"minMetaDescriptionChars": 50,
"maxMetaDescriptionChars": 160,
"minImageAltCoveragePercent": 95,
"requireCanonical": true,
"requireSameOriginCanonical": true,
"requireSingleH1": true,
"requireMainLandmark": true,
"requireFormLabels": true,
"captureScreenshots": true,
"viewportWidth": 1440,
"viewportHeight": 900
}

One to ten URLs are accepted. Internal links are deduplicated, fragment-free, same-origin only, and capped at 50 per page. Link probes use HEAD, falling back to a one-byte ranged GET when a server rejects HEAD.

Output contract

The overview record contains:

  • overall status;
  • pass, fail, unknown, page, finding, and screenshot totals;
  • one status per requested page; and
  • the exact thresholds used.

Finding records contain a stable checkId, category, severity, expected rule, observed result, short evidence array, final URL, and screenshot key/link when applicable.

unknown is used when the Actor cannot safely or conclusively run a check. It does not silently convert network, DNS, rendering, or screenshot failures into a pass.

When a maximum run charge cannot cover another page, that URL is not opened. Its only finding is budget_limit with status: unknown and audited: false. The overview separately reports requested, processed, and budget-limited URL counts, so an unpaid page is never presented as audited.

Concrete example output

This abridged output came from the verified 17 July 2026 check-landing-page-before-launch example against https://example.com/. The page rendered and produced a screenshot; the failing checks remained visible instead of being forced green.

{
"recordType": "overview",
"status": "fail",
"summary": "Release QA found 3 failing check(s) across 1 page(s)",
"totals": {
"requestedUrls": 1,
"processedUrls": 1,
"budgetLimitedUrls": 0,
"findings": 12,
"screenshots": 1,
"pass": 9,
"fail": 3,
"unknown": 0
}
}

One detailed record was:

{
"recordType": "finding",
"status": "fail",
"checkId": "main_landmark",
"category": "accessibility",
"severity": "medium",
"summary": "No main content landmark was found",
"expected": "At least one main or role=main landmark",
"observed": "0 main, 0 navigation, 0 banner, 0 contentinfo landmarks",
"audited": true
}

The screenshot is stored as SCREENSHOT_001 in the run's default key-value store. Volatile timestamps and storage URLs are omitted from this example.

Current Apify pricing

The live Store listing uses pure pay-per-event pricing with exactly two events:

  • apify-actor-start: the official platform-managed synthetic event at its default USD 0.00005 price. Apify charges it automatically and covers the first five seconds of compute; the Actor must never charge it manually;
  • page-audited: USD 0.05 once per URL, charged before browser or link work begins.

That makes event charges USD 0.05005 for one page, USD 0.25005 for five pages, and USD 0.50005 for the ten-page maximum.

page-audited is the primary event. apify-default-dataset-item and the obsolete custom audit-start event are not configured, so detailed findings cannot create a second charge. Platform usage is included in the event price.

The runtime validates the production PPE event configuration, but it does not manually charge the synthetic start. It inspects every custom-page ChargeResult: a failed page charge stops the run before that URL is processed. A successful charge remains valid even when it exhausts the remaining event budget; that already-paid page is still audited, while later pages are marked budget-limited.

The public configuration was verified on 17 July 2026 with limited permissions, hidden source files, Standby disabled, 1024 MB minimum/default memory, and a 2048 MB maximum. Owner cloud preflights for 1, 5, and 10 pages reported total platform usage of approximately USD 0.00063, USD 0.00109, and USD 0.00332. Those runs are cost and reliability evidence, not customer demand or revenue.

This charging design follows Apify's current pay-per-event guidance, including the synthetic start event, ChargeResult budget checks, and the optional platform-usage pass-through setting.

Safety boundary

  • Only public HTTP(S) URLs on ports 80 and 443 are accepted.
  • URL credentials, localhost, internal hostnames, and private, reserved, link-local, multicast, and otherwise non-public IP addresses are rejected.
  • Browser traffic is forced through a loopback-only guard proxy. The proxy resolves every destination itself and connects to the validated public IP, preventing Chromium from bypassing the DNS decision.
  • Redirect destinations and sampled links are revalidated.
  • Service workers and downloads are disabled.
  • Runs are bounded to ten pages, fifty sampled links per page, eight link requests at once, and sixty seconds per navigation or probe.
  • No account, cookie, customer credential, API key, proxy subscription, or model call is required.

What it does not claim

This is a focused release checklist, not a complete WCAG audit, legal compliance opinion, Core Web Vitals test, visual-regression system, malware scanner, or proof that search engines will index a page. It does not log in, submit forms, click consent dialogs, or intentionally perform a write action. Browser routing blocks methods other than GET, HEAD, and OPTIONS. The Actor still issues GET navigations and bounded HEAD/GET link probes, and it does not crawl beyond the configured link sample.

Dynamic pages are rendered with JavaScript, but results can still differ when a site personalizes content, geo-blocks cloud browsers, requires authentication, or delays important UI beyond DOMContentLoaded and a short bounded network-idle wait. Those cases remain visible as failures or unknowns.

Local verification

Prerequisites: Node.js 22.19+.

npm ci
npm run verify
npx --yes apify-cli@1.7.1 validate-schema

For a live local screenshot, install the matching Chromium once:

npx playwright install chromium
npm run demo

On Windows, an existing stable Chrome install can be used without downloading Chromium:

$env:WEBSITE_QA_BROWSER_CHANNEL = "chrome"
npm run demo
Remove-Item Env:WEBSITE_QA_BROWSER_CHANNEL

The demo makes read-only requests to https://example.com/, writes its PNG under output/playwright/, and prints the run overview. Unit tests inject network and browser fixtures and do not depend on public websites.

Local pay-per-event boundary check

Local PPE test events explicitly charged by Actor code cost USD 1 each. The following USD 1 cap permits exactly one custom page-audited event. The platform-managed synthetic start is deliberately not emitted by Actor code or the local charging log. The second URL must remain unaudited and appear as an explicit budget-limited result:

$env:ACTOR_TEST_PAY_PER_EVENT = "true"
$env:ACTOR_USE_CHARGING_LOG_DATASET = "true"
$env:ACTOR_MAX_TOTAL_CHARGE_USD = "1"
$env:WEBSITE_QA_BROWSER_CHANNEL = "chrome"
npx --yes apify-cli@1.7.1 run --purge --input-file demo/ppe-input.json
npm run verify-ppe-log
Remove-Item Env:ACTOR_TEST_PAY_PER_EVENT
Remove-Item Env:ACTOR_USE_CHARGING_LOG_DATASET
Remove-Item Env:ACTOR_MAX_TOTAL_CHARGE_USD
Remove-Item Env:WEBSITE_QA_BROWSER_CHANNEL

The charging log is written to storage/datasets/charging_log/. It must contain exactly one page-audited event. The default dataset overview must report one processed URL, one budget-limited URL, and one page event charged. Neither a manual start event nor a synthetic dataset event is permitted. Named local charging logs can survive Apify's --purge; verify-ppe-log therefore scopes its assertion to the current default-dataset overview timestamp.

The Actor requires at least 1024 MB of memory, matching Apify's browser-Actor guidance. The cloud Docker image pins Node.js 22 and Playwright 1.61.1 to the matching Apify Chromium image for reproducible builds.