Google PageSpeed Insights Bulk Website Auditor
Pricing
from $1.40 / 1,000 reports
Google PageSpeed Insights Bulk Website Auditor
Audit public URLs with Google PageSpeed Insights: lab performance scores, LCP, CLS, TBT, FCP, Speed Index and top opportunities, with no buyer API key.
Pricing
from $1.40 / 1,000 reports
Rating
0.0
(0)
Developer
Tim Zinin
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
8 hours ago
Last modified
Categories
Share
Audit public web pages with Google PageSpeed Insights and export structured Lighthouse lab results. Each URL and device strategy produces one report with a performance score, five lab metrics, the audit timestamp, Lighthouse version and up to five opportunities.
Evidence status (2026-09-06). The actor was built on the Apify platform (build c6lGyNqZOjP154gsY) with the operator's secret PSI_API_KEY, its pay-per-event tariff was read back from the platform, and three private acceptance runs on Apify infrastructure produced real PageSpeed Insights reports for example.com: one mobile report, one desktop report, and both strategies in one run. The rate-limit example remains a clearly labelled synthetic response fixture and the no-key example is a real local SDK run.
R1. What you get
- One complete report for each unique URL and mobile or desktop strategy.
- Native Lighthouse performanceScore on a zero-to-one scale, with zero preserved as a valid score.
- LCP, TBT, FCP and Speed Index in milliseconds, plus unitless CLS, all from lab audits.
- fetchTime and lighthouseVersion so comparisons retain the measurement context.
- Up to five source-reported opportunities or modern insights with bounded titles and savings estimates.
- Optional additional category scores and explicit free outcomes for rate limits, configuration problems and incomplete reports.
The Actor calls the PageSpeed Insights v5 runPagespeed API. It does not run a browser on Apify or operate its own Lighthouse installation. Google performs the remote page audit, and this Actor validates and projects the returned report. The output is a compact structured summary, not the full Lighthouse JSON, trace, screenshot collection or HTML report.
No buyer API key is required or accepted. The service owner supplies a secret PSI_API_KEY environment variable. If that configuration is absent, the Actor returns one explanatory row and exits normally without requesting any reports. Adding a key field to input is not a supported workaround and unknown input properties are rejected when normal input processing occurs.
R2. Who uses it
Web developers can collect comparable lab observations around a release. An agency can audit a small list of permitted client pages on mobile, desktop or both, then create a review queue from source-reported opportunities. An operations team can retain structured measurements with version and time information for trend analysis alongside its deployment history.
A Lighthouse lab run is a controlled observation of a page load, not a report of every visitor's experience. Use it to investigate possible performance work and to compare like-for-like test conditions. It is not a revenue forecast, a search ranking guarantee or proof that a page passes all real-user Core Web Vitals criteria.
Supply pages that can be audited publicly and that you are entitled to submit to Google's service. Private dashboards, authenticated areas and internal hosts are outside scope. The Actor does not accept cookies, browser credentials or private network routes. Avoid URLs containing access tokens or other sensitive query parameters even when the page is otherwise publicly accessible.
R3. How to run
- Start with the prefill: https://example.com, mobile strategy and performance category.
- Replace the URL with a permitted public page, or add a small list of pages with comparable roles.
- Add desktop if you need both device strategies. The raw URL count multiplied by strategy count must be at most 20.
- Start the run and inspect complete report rows separately from free explanations.
- Retain fetchTime, lighthouseVersion, strategy and input settings when comparing results or opening engineering tasks.
The owner configures service access outside the buyer Input form. A configuration_required row means the service owner needs to restore the secret environment configuration. It contains found=false and resultCount=0, and OUTPUT.fatal is empty. No URL or strategy is sent for audit in that path. A nonzero start charge can still apply according to the platform tariff even though no report event is emitted.
A rate_limited result is different from missing configuration. It means an API request encountered quota or throttling after the bounded retry policy. Starting more concurrent runs is unlikely to help a shared quota problem. Keep the returned error and run ID, then retry later or contact the operator rather than inserting your own source key into input.
R4. Pricing
The tariff is $0.003 per start + $0.002 per complete report, read back from the platform on 2026-09-06 (apify-actor-start $0.003, result-found $0.002, model PAY_PER_EVENT). A report is one URL times one strategy, regardless of the number of selected categories. One complete mobile report therefore costs $0.005 including one default-memory start event. One URL on both strategies costs $0.007, ten complete reports cost $0.023, and the maximum 20 complete reports cost $0.043 at that tariff.
Platform evidence for the tariff above (charged event counts of the accepted runs): mobile report 92KDaNEkYGfORva60 result-found: 1; desktop report ZT6wOzLbVg69SVMJj 1; both strategies NghEjQCJHx774Xbzj 2. The start event is charged once per GB of run memory: the acceptance runs were started with 4096 MB and therefore show apify-actor-start: 4, while a run at the default memory pays one start unit per GB.
The default memory is 256 MB. Platform start events can depend on the configured memory allocation, so verify the actual start-event count when changing that setting. The calculations above are not a platform cost measurement or a guarantee about your account credits. The published Console tariff and charged-event readback must be checked before release and production use.
A missing key, exhausted 429, source error, malformed response, missing required metric or documented limit produces no result-found event for that row. A low or zero performance score is still a complete useful report when the required lab evidence is valid. The Actor does not charge only for good scores or only for pages with recommendations.
Reports completed before a later failure remain billable and available. Transport retries do not themselves create report events. A separately started run can bill the same URL and strategy again, even if the page is unchanged. There is no persistent cross-run deduplication or free monitoring ledger. Category choices do not multiply events, while adding a second strategy does.
R5. Input contract
| Field | Default | Contract |
|---|---|---|
| urls | ["https://example.com"] | 1–20 public HTTP(S) URLs without credentials or nonstandard ports. URLs × strategies must be at most 20 before deduplication. |
| strategies | ["mobile"] | mobile and/or desktop, maximum 2 entries. Each unique URL × strategy is one report. Invalid values are rejected at runtime. |
| categories | ["performance"] | performance, accessibility, best-practices and/or seo (1–4 entries). Performance is always included to supply the required lab metrics. |
{"urls": ["https://example.com"],"strategies": ["mobile"],"categories": ["performance"]}
urls contains one through 20 public HTTP(S) URL strings, each at most 2,048 characters. Credentials and nonstandard ports are rejected, as are localhost names and private IP literals. The runtime also resolves target DNS before submitting the URL and refuses private or unavailable destinations. URL fragments are removed and equivalent normalized URL strings are deduplicated within the run.
strategies contains mobile, desktop or both, with at most two entries. Categories may contain performance, accessibility, best-practices and seo, with at most four entries. Runtime validation enforces these values even when a JSON client bypasses the form. Uppercase variants, empty arrays, arbitrary category names and unknown input fields are invalid. Duplicate entries do not create extra report work, but the raw array product is checked before deduplication.
Performance is always included in the effective category set because this report contract requires its score and lab metrics. Selecting only seo therefore also requests performance. Additional effective categories are exposed in categoryScores. The Actor refuses a response that lacks a valid score for a requested category rather than silently omitting the requested evidence.
The 20-report cap is a maximum request scope, not a guarantee that 20 remote audits fit within one run's working deadline or your spending cap. A slow upstream audit or shared quota can reduce delivered reports. Prefer small batches when latency matters, and preserve completed reports before retrying the remaining scope.
R6. Accepted platform run examples, fixture and no-key examples (2026-09-06)
Accepted platform run 92KDaNEkYGfORva60 (mobile report for example.com), input and the unedited paid dataset row:
{"input": {"urls": ["https://example.com"],"strategies": ["mobile"],"categories": ["performance"]},"output": {"input": "https://example.com/","sourceUrl": "https://www.googleapis.com/pagespeedonline/v5/runPagespeed","found": true,"status": "ok","resultCount": 1,"partial": false,"error": "","warnings": [],"checkedAt": "2026-09-05T21:18:43.387Z","schemaVersion": "1.0","url": "https://example.com/","strategy": "mobile","finalUrl": "https://example.com/","performanceScore": 1,"LCP": 756,"CLS": 0,"TBT": 0,"FCP": 756,"SI": 756,"metricSource": "lab","metricUnits": {"LCP": "ms","CLS": "unitless","TBT": "ms","FCP": "ms","SI": "ms"},"fetchTime": "2026-09-05T21:18:38.636Z","lighthouseVersion": "13.4.1","topOpportunities": [],"categoryScores": {"performance": 1}}}
Accepted platform run ZT6wOzLbVg69SVMJj (desktop report), unedited paid dataset row:
{"input": "https://example.com/","sourceUrl": "https://www.googleapis.com/pagespeedonline/v5/runPagespeed","found": true,"status": "ok","resultCount": 1,"partial": false,"error": "","warnings": [],"checkedAt": "2026-09-05T21:19:54.329Z","schemaVersion": "1.0","url": "https://example.com/","strategy": "desktop","finalUrl": "https://example.com/","performanceScore": 1,"LCP": 208,"CLS": 0,"TBT": 0,"FCP": 208,"SI": 208,"metricSource": "lab","metricUnits": {"LCP": "ms","CLS": "unitless","TBT": "ms","FCP": "ms","SI": "ms"},"fetchTime": "2026-09-05T21:19:49.288Z","lighthouseVersion": "13.4.1","topOpportunities": [],"categoryScores": {"performance": 1}}
Synthetic rate-limited input and observed output excerpt (opportunities excerpted to two entries when present):
{"input": {"urls": ["https://example.com"],"strategies": ["mobile"],"categories": ["performance"]},"row": {"input": "https://example.com/","sourceUrl": "https://www.googleapis.com/pagespeedonline/v5/runPagespeed","found": false,"status": "rate_limited","resultCount": 0,"partial": false,"error": "PageSpeed quota/rate limit after bounded Retry-After retries","warnings": [],"checkedAt": "2026-09-05T19:51:30.459Z","schemaVersion": "1.0","url": "https://example.com/","strategy": "mobile"}}
Real SDK local no-key output and summary excerpt:
{"row": {"input": null,"sourceUrl": "https://www.googleapis.com/pagespeedonline/v5/runPagespeed","found": false,"status": "configuration_required","resultCount": 0,"partial": false,"error": "Service owner must configure secret PSI_API_KEY. No buyer key is required; no report was requested or billed.","warnings": [],"checkedAt": "2026-09-05T19:51:59.303Z","schemaVersion": "1.0"},"summary": {"requested": 0,"free": 1,"paid": 0,"fatal": "","configurationRequired": true}}
The mobile and desktop rows above are dataset items of the accepted platform runs executed on Apify infrastructure on 2026-09-06 with the deployed build, the operator key and the live tariff; run NghEjQCJHx774Xbzj delivered both strategies for one URL as two paid rows. The output uses lab values and does not substitute loadingExperience or originLoadingExperience data; field data, when present, stays in its own fields.
The no-key example comes from main.js running on the real Apify SDK locally. It produced one configuration_required dataset row, OUTPUT.free=1, OUTPUT.paid=0 and an empty fatal string, then exited with code zero. The sandbox prevented an SDK memory snapshot subprocess, which is recorded in the local log; it did not prevent normal Actor completion. This is a control-flow proof, not a measurement of Apify platform resources or billable events.
The fixture rate-limit example returns a free failure after request handling. Separate transport tests verify Retry-After and the maximum two retries; an injected final 429 response alone would not prove the retry loop. The operator should perform a live owner-key platform run before publishing a default input as healthy.
R7. Field dictionary and metric interpretation
| Field | Contract |
|---|---|
| url | Normalized requested public URL, with fragment removed. |
| strategy | mobile or desktop for this report; part of the report identity. |
| finalUrl | Google's reported audited destination, validated before delivery. |
| performanceScore | Lighthouse performance category score from 0 through 1. Multiply by 100 only for a percentage-style display. |
| LCP | Largest Contentful Paint audit numericValue in milliseconds. |
| CLS | Cumulative Layout Shift audit numericValue, unitless. |
| TBT | Total Blocking Time audit numericValue in milliseconds. |
| FCP | First Contentful Paint audit numericValue in milliseconds. |
| SI | Speed Index audit numericValue in milliseconds. |
| metricSource | Always lab in a complete report from this Actor. |
| metricUnits | Explicit mapping of timing fields to ms and CLS to unitless. |
| fetchTime | Timestamp from the Lighthouse result. |
| lighthouseVersion | Version string reported by the remote Lighthouse run. |
| topOpportunities | Up to five bounded opportunity/insight objects with source savings evidence. |
| categoryScores | Effective requested categories and their native zero-to-one scores. |
| warnings | Up to 20 bounded Lighthouse warning strings. |
| sourceUrl | Fixed PageSpeed API method URL without a key or target query. |
| checkedAt | Actor projection timestamp, separate from Google's fetchTime. |
| found and resultCount | True and one for a complete report; false and zero for free outcome rows. |
| partial / error | Completeness indicator and explanatory string; limits have a nonempty explanation but are nonfatal. |
| schemaVersion | Version of this projected output contract, currently 1.0. |
The five metric values come from their individual Lighthouse audits: largest-contentful-paint, cumulative-layout-shift, total-blocking-time, first-contentful-paint and speed-index. They are numeric values, not parsed display strings. Display text can be localized or rounded, so extracting numbers from it would introduce avoidable ambiguity. The Actor instead requires finite, nonnegative numeric values for every metric in the complete report contract.
Zero is valid. A zero TBT or CLS does not mean the field is missing, and a zero performanceScore is not an API failure. Conversely, null, a numeric string or an audit error is not silently converted to zero. If a required metric cannot be established, the Actor emits a free incomplete-report error rather than selling a partly populated result as complete.
The performance score is not the arithmetic mean of the five displayed values. It is the category score returned by Lighthouse. This Actor does not reproduce Google's scoring formula, normalize values to a target device or infer a ranking. Preserve the source score and metric units if you calculate a separate application-specific priority measure.
fetchTime describes the remote Lighthouse result; checkedAt describes when the Actor validated and projected it. Neither field is a page publication date or your deployment timestamp. Attach deployment information from your own release system when doing before-and-after analysis. A report with a new checkedAt can still require inspection of fetchTime to understand exactly which remote observation it represents.
A topOpportunities entry contains id, title, description, displayValue, estimatedSavingsMs, estimatedSavingsBytes and metricSavings. The Actor includes positive savings from legacy opportunity details and modern insight metricSavings. It sorts by the largest millisecond saving, then byte saving, then ID, and returns at most five. A CLS saving remains unitless and is not treated as a millisecond quantity.
An opportunity's estimate is source-reported diagnostic evidence. Savings for different audits can overlap and should not be summed into a promise of total page improvement. The largest estimate is a starting point for investigation, not an instruction to make a code change without reviewing dependencies and the actual implementation. Descriptions can contain markup or links and remain untrusted source text.
An empty opportunities list can accompany a complete report. It means the projection found no eligible positive saving estimates in the returned audits, not that the page has no remaining engineering work. Some audits are informative, manual, passed or missing a quantified savings field. They are not turned into invented recommendations merely to fill five slots.
R8. Evidence and boundaries
The owner provides one service key restricted to the PageSpeed API. It is read only from the secret environment, transmitted through X-Goog-Api-Key to the exact fixed method request, and removed from output strings if echoed by upstream content. It is never included in sourceUrl, a generated query string, the input form or a README example. The Actor does not write a secret file or expose a key through a configuration result.
The Actor's own HTTP transport validates all DNS answers, pins the connection and checks every redirect. For PSI, redirects must preserve the exact full API request URL before the key header can be forwarded. A redirect to another host or a different request is refused. Target URL DNS is checked before submission, and the final reported target is checked before a complete report is delivered.
Google operates the remote Lighthouse browser. The Actor cannot pin Google's DNS lookups or observe every browser navigation hop inside Google's service. The SSRF guarantees for the Actor's own API connections do not imply control over that remote browser. Internal/private targets are rejected locally, and only permitted public pages belong in the input.
There is a 90-second timeout for an individual PSI response, a 20-second DNS bound, a 240-second working deadline and a 300-second platform run timeout. Responses are capped at 10 MB, total downloads at 100 MB, request reservations at 80 and projected report output at 100 KB. Upstream report blobs and unrelated traces are not exported. Sequential operation avoids generating a burst of 20 concurrent Lighthouse requests.
At most two transient retries follow an initial request. HTTP 429 honors Retry-After as seconds or an HTTP date, within the remaining working deadline. If the required wait no longer fits, the Actor returns the failure instead of sleeping past the run budget. A malformed HTTP200 report is not retried as though it were a network outage.
Documented limits are free nonfatal results. A run containing only a byte/deadline limit has fatal="". A limit plus a real failed report also remains nonfatal at run level while preserving the error row. If all requested reports actually fail, fatal is All reports failed and the run fails. A mixed completed report and failure marks the overall run partial and keeps the earlier complete report.
R9. Decision routing
| Outcome | Operational interpretation | Suggested action |
|---|---|---|
| Complete report | Required lab evidence was validated for one URL and strategy. | Store it with time/version and compare like-for-like observations. |
| Low or zero score | A valid diagnostic result, not a transport failure. | Review source metrics and opportunities before prioritizing work. |
| Empty opportunities | No eligible quantified opportunity was projected. | Keep the report; do not invent five recommendations. |
| configuration_required | No owner key was configured; no reports were requested. | Contact the service operator and avoid adding a buyer secret to input. |
| rate_limited | Shared quota or throttling remained after bounded retries. | Retry later or ask the operator to inspect quota. |
| invalid_response | Required report evidence, identity or strategy could not be validated. | Retain the failure and inspect the upstream/implementation change. |
| limit_exceeded | A documented work or size bound stopped the report. | Reduce batch scope or review the page, then retry remaining work. |
| budgetExhausted | Remaining funds could not cover another complete report. | Preserve completed pairs and plan a new smaller batch. |
Do not use a free error row as a numeric score of zero in a dashboard. That would make an API outage look like a performance regression. Store outcome status alongside nullable metric columns and exclude unsuccessful reports from averages while displaying the missing observations separately. A missing measurement is operationally important even when it does not belong in a score chart.
R10. Commercial playbooks
Compare a release on one public page
Choose a permitted page whose role and content remain comparable across a release. Run the same strategy and categories before and after the change, retaining fetchTime, Lighthouse version and deployment ID. Inspect multiple observations when you need to judge variability; one run is an observation, not a statistically established improvement.
If the upstream Lighthouse version changes between observations, annotate the comparison. A changed score or opportunity list can reflect a measurement change as well as a site change. Review the numeric audits and the actual release diff before attributing a difference to one optimization. The Actor preserves the version so your reporting layer can make this distinction visible.
Prepare an agency review queue
Audit a small set of authorized client pages, then create one review item per URL and strategy with the strongest source opportunity and its evidence. Include the metric values, time and version rather than only a red/green score. A developer needs enough context to reproduce the concern and decide which code path to inspect.
Keep mobile and desktop as separate observations. A high desktop score does not erase a mobile issue, and combining them into one unlabelled average hides the test context. Categories such as accessibility or SEO can add review signals, but an automated category score is not a complete manual accessibility or compliance audit.
Monitor a representative page set
Choose page roles such as homepage, content page and product page based on your own site's structure. Keep the batch within 20 URL-strategy pairs and use a schedule that provides useful evidence without exhausting shared quota. Store the selected page role in your destination mapping; the Actor does not infer business criticality from the URL.
Report missing observations and limits explicitly. If only half a batch completed, do not present its average as the whole page set's health. Retain completed reports, identify which pairs remain unprocessed or failed, and make the next run focus on the missing scope when appropriate. A new run can bill repeated pairs again.
Turn diagnostic estimates into engineering work
Use an opportunity ID and source title as a pointer for investigation. Preserve the estimated saving with its metric or byte unit, and avoid summing overlapping estimates. Add your own reproduction steps, code ownership and expected change only after reviewing the actual page and repository. The Actor supplies diagnostic evidence; it does not verify a proposed code fix.
After a change, repeat the same permitted audit configuration and compare the relevant metrics and source observations. Record tradeoffs such as a layout change or altered content rather than attributing every numerical difference to an optimization. Do not attach revenue or search ranking guarantees to a lab estimate.
R11. Integration recipes
Run once from the Apify Console
Start with the supplied prefill and inspect the resulting dataset before connecting a production destination. The Input tab is a form for the documented input object. Unknown properties are rejected by the runtime even if a client permits sending them. Keep the first run small enough that a human can inspect every result. Export JSON when the result includes arrays or objects: a spreadsheet export is useful for an overview, but a nested value in one CSV cell is not a normalized relational table.
After the run, inspect the run state, the dataset and the OUTPUT summary together. A dataset can contain useful rows even when the run later fails. A successful run can contain a documented free limit notice. A nonempty dataset alone therefore cannot drive a success notification. For a full import, require a clean source status, the expected identity fields, the expected schemaVersion, and a summary that accounts for every requested input. For an incremental import, keep complete rows and separately route incomplete work for review.
Call the asynchronous API
Use the Actor API documentation shown in the Console to copy the current endpoint for this Actor. Send a JSON input body to the run endpoint, authenticate through the Authorization header, and retain the returned run ID before waiting for completion. A run may take longer than a short HTTP client timeout. Poll the run endpoint with bounded backoff, or use a completion webhook, then obtain the dataset ID from that run. Do not substitute the Actor's most recent run: another scheduled or interactive invocation could have started in the meantime.
Keep the platform token in your automation's secret storage. It authenticates your Apify account and is separate from any source service configuration. Do not put it in source URLs, dataset fields, spreadsheet columns, screenshots or support tickets. If a client prints complete request URLs, use Authorization headers so ordinary request logging does not reveal the platform token. Examples in this manual intentionally contain no usable credentials.
Retrieve and page through results
Read the dataset associated with the completed run. Use a page size supported by the platform and continue until all items are retrieved. Free explanations occupy dataset rows, so the number of dataset items is not the number of billed results. The source cap and the dataset retrieval page size are different controls: changing a download page size cannot recover source data that the Actor deliberately did not fetch. Preserve the original dataset index alongside your transformed record when you need an audit trail.
For a destination that only accepts flat records, flatten after checking the outer row status. Repeat the outer source identity and checkedAt on each child row. Assign an explicit child index or domain key; do not rely on destination row order as an identity. Keep arrays of warnings and provenance in a companion JSON record if the destination cannot represent them. Test that empty strings, zero, false and null retain their different meanings after the transformation.
The dataset is the detailed result channel; OUTPUT is the aggregate accounting channel. Archive both with the input JSON and the run ID. A dashboard that stores only the success rows loses the reason an input was missing. A dashboard that stores only OUTPUT loses the actual evidence behind a result. Retaining both lets support distinguish a source change, a permission change, a configured limit and a delivery failure without rerunning the source.
Use n8n
Create a small workflow with a manual trigger, a node that starts this Actor, a wait or polling step, a dataset read step and an IF or Switch node. Route complete results to the importer, clean absence to a review branch, and errors or limits to a separate operational queue. Avoid a workflow that maps every returned row directly into a production table. A free explanatory row intentionally does not have every field of a complete result.
In the import branch, retain sourceUrl, checkedAt, schemaVersion and the domain identity. Use an upsert key appropriate to your destination instead of blind insertion. Put a unique constraint on your own job ID plus result identity if your webhook handler can run more than once. If the destination rejects a row, retry the destination write from the saved dataset; there is usually no reason to start another source run and pay to retrieve evidence you already have.
Set the workflow timeout above the Actor's expected run duration and use a bounded polling schedule. A stopped or failed run must leave the workflow's waiting state. Record the run ID in failure notifications, but avoid embedding entire source records when they contain information your notification channel should not receive. Test the negative and partial branches with the examples in this manual before enabling a schedule.
Use Make or Zapier
Build the scenario around a completed run, then retrieve its dataset. An iterator over dataset items should be followed by a filter on the documented status and completeness fields. Name branches by their operational meaning: import, no current result, retry source later, and investigate configuration. Include a final count comparison so a scenario that silently drops a row cannot report a complete import.
If a run yields nested arrays, decide whether the destination expects one object per result or one object per child record. Expanding nested arrays can multiply automation tasks even though it does not create extra Actor result events. Estimate those destination operations separately from this Actor's tariff. The Actor's result price is not a quote for third-party workflow subscriptions, destination API usage or your own data storage.
Schedules belong to the automation or to Apify. Avoid enabling both for the same job unless you intentionally want two independent polling streams. Include the exact input configuration in your job description, because a copied scenario can keep an older cap or strategy without anyone noticing. After an input change, perform one manual run and inspect both a complete result and the new summary before resuming recurring execution.
Use a completion webhook
A webhook signals that a run reached a terminal state; it is not itself the complete dataset. Read the run ID from the event, resolve that run's dataset, and process it using an idempotent destination operation. Webhook systems can deliver the same event more than once. Keep a processed-event record and reject duplicate destination work without assuming that a second notification means the Actor ran twice.
Keep webhook verification and destination credentials in your receiving service. The Actor does not accept arbitrary callback URLs in its input and does not send your extracted data to a buyer-supplied endpoint. Configure platform webhooks through the platform's supported controls. This keeps source retrieval separate from your choice of destination and makes it possible to replay destination processing from a saved dataset.
Treat terminal FAILED and successful partial runs as different cases. A failed run requires inspection of its summary and log; a successful limit run requires a decision about the missing scope. Neither should trigger an automatic delete in your destination. If you notify a team, include a short status, the run ID and a link to the retained evidence rather than a claim that the source has no data.
Load a warehouse or database
Use a staging table before merging into a production table. Store the raw JSON with a run ID, dataset index and ingestion timestamp, then project domain fields into typed columns. This preserves the ability to correct a transformation without fetching the source again. The original checkedAt describes the Actor observation; your ingestion timestamp describes arrival at the destination. Keeping both exposes queue delays.
Choose a uniqueness policy before importing historical runs. A current-state table often uses the source identity as its key and updates on later observations. A history table uses the identity plus observation or run ID. These are different products: overwriting a current-state table cannot later answer historical questions, while appending every retry into a history table can create misleading duplicate observations.
Do not infer a deletion from the absence of a source identity in a partial run. First establish that the requested scope was complete, the source returned the expected form, and all dataset pages were ingested. For a destructive synchronization, require a separate complete-run marker and an explicit downstream policy. This Actor provides evidence and accounting; it does not issue deletion commands to your catalog, CRM or warehouse.
Pass results to an LLM or retrieval pipeline
Filter and normalize the structured output before constructing a prompt. Source text is untrusted content, including product copy, spreadsheet cells and diagnostic titles. Keep it in a clearly separated data field and do not interpret embedded instructions as workflow commands. A source string that asks an assistant to reveal secrets or call a URL remains a source string. The Actor does not execute it.
Retain provenance when chunking results for retrieval. Each chunk should point back to the source identity, checkedAt and run ID. If a response is incomplete, carry that state into the retrieval index metadata so an answer does not present a partial snapshot as a complete source. Generated summaries should link to the structured evidence and should not replace the original fields used for calculations.
Limit the fields sent to the model to the actual task. Numeric values should be calculated in your application when exact arithmetic matters. Treat an LLM's interpretation as a separate derived artifact with its own model and prompt version. The Actor's schemaVersion describes this extraction contract; it does not describe the accuracy of a downstream model or the provenance of a generated narrative.
R12. Operating guide
Start with a baseline
Record a first small run with its input, date, runtime, result counts and actual platform charge. Compare the result to the source manually. Keep this baseline when you later change a cap, URL set or downstream mapping. If output changes after a source update, a baseline helps distinguish an extraction defect from a legitimate change in the source. Do not treat the included synthetic controls as representative customer volume or as proof of commercial demand.
Use the Console's currently displayed price as the commercial authority. The price in this manual was read back from the deployed tariff on 2026-09-06; check the Store page before a large run, because a tariff change is an operator action. Startup, complete result events and free status rows are separate concepts. A free result status means no result-found event for that row; it does not imply that all platform or account costs vanish, and an Actor with a nonzero start event can still have a startup charge on an empty run.
Set a spending cap
Set the platform's maximum total charge for the run according to the number of complete units you intend to buy, allowing for any start charge shown in the Console. The Actor checks remaining money immediately before each paid dataset write. If the next complete unit does not fit, it stops paid delivery. A cap is a financial limit, not a promise that the Actor will retrieve exactly a certain number of source units.
A smaller cap can stop a run before all requested inputs are processed. Inspect budgetExhausted and unprocessed in OUTPUT, and retain whatever complete results were delivered. Raising the cap later requires another run; it does not resume the previous run through an internal replay ledger. If you only need to finish a subset, construct a smaller input from the remaining work instead of repeating every successful source.
A failure to read pricing or budget is different from normal exhaustion. The Actor stops with a fatal explanation rather than treating unknown money as unlimited. If automatic dataset items have a nonzero price, the Actor refuses dataset writes, including explanations that would otherwise be free. In that condition the log is the explanation channel. Contact support with the run ID; repeatedly rerunning the same broken pricing configuration is not a remedy.
Understand delivery uncertainty
A paid result is sent using a linked dataset write and result event. If a remote write or charge operation fails, it can be impossible for the client to know whether the row landed. The Actor stops and records deliveryUncertain rather than retrying the same row automatically. This prevents a silent duplicate, but it also means that a failed run can require reconciliation against the platform's actual dataset and charged-event counts.
For a destination integration, a dataset row is evidence of a delivered record, while OUTPUT.paid records the SDK-confirmed count. Investigate any uncertainty instead of equating those quantities mechanically. If support needs a reproduction, provide the smallest input that demonstrates the issue and the original run ID. Avoid deleting the evidence or restarting multiple times before the original state has been inspected.
Plan schedules around source behavior
Choose a polling interval that reflects how often the source can usefully change and how soon your decision needs fresh evidence. A schedule does not make an upstream cache fresh. Repeated identical runs can be billed again and may not add useful information. Begin with manual or infrequent execution and increase frequency only after observing actual changes and operational value.
The implementation runs source work sequentially. This keeps request pressure and memory usage bounded and makes small runs easy to inspect. Increasing the number of URLs does not create parallel workers. The platform timeout is 300 seconds with a 240-second working deadline. The remaining time is reserved for delivery and summary work, but the platform can still interrupt a process for reasons outside the source request path.
There are at most two retries after an initial transient request failure. Only network failures, HTTP 429 and server errors qualify; a malformed successful body or ordinary client error is not repeatedly fetched. Retry-After is honored within the remaining working deadline. If the requested wait no longer fits, the Actor returns the appropriate free explanation and stops that source attempt. This is a bounded retry policy, not a guarantee that a busy upstream service becomes available.
Read the summary as a ledger
requested is the number of normalized source work units requested by the run. processed records units whose domain processing reached an output decision; its exact unit is explained in the product-specific contract. unprocessed records the remainder. delivered counts complete result rows confirmed by the delivery path. paid counts confirmed result events when running with monetized pricing; local development can deliver results with paid equal to zero.
free counts explanatory or clean absence rows written without result-found. failed counts free rows that describe actual errors, excluding documented limit_exceeded results. A free row may still contain a partial snapshot for inspection. partial indicates incomplete source scope, output, budget coverage or a fatal interruption. fatal is an empty string for a normal complete run and for documented nonfatal limits; a nonempty string explains a run-level failure.
replaySafe is false because the Actor does not maintain a persistent ledger across runs. checkedAt in OUTPUT is the summary time and can be later than each row's checkedAt. Keep row timestamps for source comparisons. A summary is deliberately small and does not duplicate all the data. If writing the summary itself fails, the log and terminal run state become necessary evidence for troubleshooting.
Monitor useful signals
Track runs that produce complete results, clean absence, source errors, limits and budget exhaustion as separate categories. A rising number of free rows can indicate either correctly enforced limits or a failing source; the status tells you which. Alert on repeated source failures or missing configuration, and review recurring limits against your intended input size. Do not use dataset row count alone as a health metric.
Track source request duration and run duration separately if your observability stack supports them. Startup, retries, throttling and destination processing can all contribute to end-to-end delay. A fast source request does not prove that a whole automation completed quickly. Conversely, a slow upstream result does not imply a broken dataset importer. Preserve the run ID through each system so latency can be traced.
Change one control at a time
When investigating a failure, keep the source and other controls fixed while changing one relevant limit or option. Compare the status, extracted values and summary to the baseline. If a permission problem is suspected, have the source owner verify access through the documented public route. Do not add credentials to a URL or try a different unapproved route to make a free error disappear.
When a schema or source changes, run a small comparison before switching a scheduled destination. Verify identifiers, numeric units, missing-value behavior, nested arrays and the clean absence branch. A transformation that works for a happy result can still fail on a documented status row. Version your own mapping independently from the Actor input so you can roll back a destination change without reverting the source configuration.
Prepare a useful support report
Include the Actor name, run ID, input with sensitive values removed, expected behavior, observed status and the relevant row or summary fragment. State whether the problem reproduced once or repeatedly and whether the source changed recently. Include a source URL only if you can share it safely. Do not send API keys, platform tokens, cookies or private source documents to a public issue.
For numeric discrepancies, include the original structured value and its unit rather than only a screenshot of a formatted cell. For missing records, include the configured caps and completeness state. For a suspected billing discrepancy, retain the platform's actual event counts and the run memory setting. These details let support isolate the responsible layer without guessing from an incomplete screenshot.
R13. FAQ
Do I need my own Google API key? No. Service access belongs to the operator and is supplied through a secret environment variable. There is no buyer-key input field or BYOK mode.
Why did a run return only configuration_required? The owner key was missing or blank. The Actor emitted one free explanation and exited normally before DNS checks or API requests. The operator must restore configuration before real reports can be requested.
Is performanceScore 83 or 0.83? The output uses the native zero-to-one score, so 0.83 is the stored value. A dashboard can display 83 after an explicit multiplication. Do not compare a zero-to-one threshold with a zero-to-100 value accidentally.
Are these real-user Core Web Vitals? No. The five metrics are lab Lighthouse audit values. The Actor does not substitute Chrome UX Report or origin field data and does not claim an overall real-user pass result.
Why does selecting SEO also request performance? The output contract requires performanceScore and its five lab metrics. Performance is included in the effective category set, and additional scores appear in categoryScores without creating another report event.
Can a report with a score of zero be paid? Yes. A valid zero score is diagnostic evidence. Missing or invalid evidence is a free error, which is a different outcome.
Why does one URL on two strategies cost two reports? Google performs a separate mobile or desktop audit for each strategy. Categories within the same strategy do not create additional report units.
Will 20 reports always finish? No. That is the input cap. Slow audits, working deadlines, shared quota and spending limits can stop a batch earlier. Inspect processed, unprocessed, partial and the row statuses.
Can I audit a logged-in page? No. Cookies, credentials and private network access are outside scope. Use a permitted public page rather than embedding access tokens in a URL.
Can I add custom Lighthouse settings or locale? Not through this input contract. It exposes URLs, strategies and categories. Extra API parameters are rejected rather than forwarded blindly.
Can I add the estimated savings together? Not as a guaranteed total improvement. Source opportunities can overlap or depend on one another. Use them to identify work to investigate and verify any actual improvement separately.
Why is an empty topOpportunities array valid? A complete report can have no eligible positive quantified saving estimate. The Actor does not invent recommendations to reach a fixed list length.
Does a newer report prove the website changed? No. Lab variability, upstream Lighthouse versions, network conditions and content can all affect observations. Keep the measurement context and review changes before making a causal claim.
Are report text and URLs trusted? Treat them as source data. The Actor does not execute recommendations, fetch arbitrary embedded links or turn source text into automation instructions.
R14. Sources, rights and support
The API contract is documented in Google's runPagespeed reference. The owner-key header follows Google API system parameters. This implementation exports a specific bounded subset of the response; consult this manual's field dictionary for its exact units and completeness rules.
The included fixture was authored for regression testing and carries its own RIGHTS file. Its measurements are synthetic, not copied from a live third-party performance report. Owner-key live reports and quota observations are separate release evidence and must not be inferred from a successful fixture test.
Operate on pages you own or are entitled to submit for auditing. Sending a public URL to PageSpeed involves Google's service and applicable terms. Do not submit confidential query parameters or private page content to work around an access problem. The Actor provides lab evidence and does not certify legal compliance, accessibility, security or search ranking.
For support, use the Actor page's issue channel with a run ID, the URL only if it is safe to share, the selected strategies/categories and the observed status. Never post the owner key or a platform token. Include fetchTime and lighthouseVersion for a report-comparison issue, and preserve the error row for a quota or configuration issue. The related-tool links and the platform examples above are final; the two Store diagrams are added after publication.
Related tools
Related tools for adjacent workflows in AI and search visibility.
| Actor | What it does |
|---|---|
| llms.txt Auditor & AI Crawler Policy Checker | Pair it in the AI and search visibility workflow: Audit public llms.txt, llms-full.txt, and root robots.txt rules for nine named AI crawlers |
| AI Answer & Citation Change Monitor | Pair it in the AI and search visibility workflow: Monitor grounded AI answers by query, model, and language; detect rewrites and cited-domain additions or... |
| AI Crawler Access Checker | Pair it in the AI and search visibility workflow: Audit up to 100 sites for 16 AI crawler policies |
| AI Overview Citation Tracker | Pair it in the AI and search visibility workflow: Track which public URLs and domains selected grounded AI models cite for buyer-supplied queries |
| Domain Health Checker | Pair it in the AI and search visibility workflow: Audit DNS resolution, MX, SPF, DMARC, name servers, and TLS for a list of domains |