Export one finalized Search Console day at a time, preserve the exact request and raw response, paginate in 25,000-row increments until an empty response, and run a less-dimensional reconciliation query. Keep provisional data separate and state that detailed page or query exports may omit rows.
- Search Console dates are defined in Pacific Time, so extraction jobs must not silently use the analyst's local date.
- Preserve request JSON, raw responses, pagination metadata, retrieval time, and extractor version before transformation.
- Detailed query and page exports can represent less than aggregate totals; reconciliation should expose that gap rather than manufacture missing rows.
- Fresh and finalized data should remain distinguishable throughout the pipeline.
01
Preconditions
A reproducible Search Console export begins with a defined dataset, not with a spreadsheet button. Record the exact Search Console property, search type, date range, dimensions in order, aggregation type, filters, regular expressions, data state, and extraction version. Google calculates and exposes data differently when page or query dimensions are included, so two requests that look similar to a person can represent materially different datasets. [2] [4]
Use the read-only OAuth scope when the job only reads data. Confirm that the account or service identity can access the intended property, and keep authorization separate from the exported records. The extraction should be idempotent: rerunning the same dataset definition should replace or version the same logical partition rather than append duplicate rows.
Resolve target dates in Pacific Time. Google's documentation says Search Console performance dates use the America/Los_Angeles time zone, not the analyst's local zone. It also says performance data is typically available after two to three days. A conservative daily job can therefore extract the day three days earlier, with an explicit later recheck when the business needs additional certainty. [1]
Create two storage layers before the first production run. The raw layer should preserve the request and untouched response. The modeled layer can expand dimension keys, standardize columns, and support reporting. At minimum, the raw record should include the property, request JSON, request hash, retrieval timestamp, target Pacific date, data state, response aggregation type, page number, start row, raw response location, and extractor version.
02
Ordered process
- Resolve the target dataset. Determine the finalized Pacific date and load a version-controlled request definition. A stable request might specify one day,
websearch type, ordered dimensions such as page, query, country, and device,aggregationType: auto,dataState: final,rowLimit: 25000, andstartRow: 0. Do not silently alter filters or dimension order between runs because the dataset identity would change.
- Verify availability with a small query. Run a low-dimensional request grouped by date before starting the detailed extraction. This separates an unavailable date from an unexpectedly empty detailed result. Archive that availability check with the job record. Google's guide explains that data usually arrives after a delay, so an empty recent date should not automatically be interpreted as zero search activity. [1]
- Page until the API returns no rows. Set
rowLimitto 25,000 and incrementstartRowby the same amount after each response. Save every request and raw response before transforming it. Google's official guide uses an empty response as the unambiguous stopping condition and states that this method exposes no more than 50,000 rows per day per search type. [1]
start_row = 0
row_limit = 25_000
while True:
request = {**base_request, "startRow": start_row, "rowLimit": row_limit}
response = query_search_analytics(request)
save_raw_response(request, response)
rows = response.get("rows", [])
if not rows:
break
upsert_rows(dataset_id, rows)
start_row += row_limit- Normalize without discarding provenance. Expand the ordered
keysarray into named dimension columns and store clicks, impressions, CTR, and position. Keep a foreign key or digest back to the raw response. Transformations should be deterministic and versioned. A dashboard table is not a substitute for the source payload, because future analysts will eventually discover that today's convenient cleanup removed tomorrow's needed distinction.
- Run a reconciliation query. For the same property, date, search type, filters, and aggregation, issue a second request with fewer dimensions, especially without page and query when a more complete total is desired. Compare detailed clicks and impressions with the reconciliation totals. Google warns that page and query dimensions can cause some data to be dropped, so the two totals are not required to match. [2] [4]
- Calculate and publish coverage. A useful coverage ratio is detailed-export clicks or impressions divided by the corresponding reconciliation total. Label it as represented coverage, not as an error rate. Never distribute an unexplained remainder across visible rows. That would convert omitted data into invented precision.
- Separate provisional data. When
dataStateisall, the response may include fresh, incomplete data and metadata such asfirst_incomplete_date. Keep those rows in a provisional partition or mark them clearly. Use finalized data for durable reporting, provisional data for operational monitoring, and replace provisional rows after finalization. The request reference documents the available data states and incomplete-date metadata. [2]
- Discover search-appearance values before filtering them. Google recommends querying
searchAppearanceby itself to identify the values available to the property, then running separate filtered requests for each relevant appearance. Do not rely permanently on a hard-coded list because Search features are introduced, renamed, and retired. [1]
- Log quotas and failures explicitly. Record quota errors, authorization failures, schema changes, unexpected empty dates, request-hash mismatches, and reconciliation shifts. Google's quota documentation defines current load and request limits, but those limits can change. Retry bounded transient failures and fail loudly when the dataset cannot be proven complete under its own definition. [3]
- Publish a dataset manifest with every reporting refresh. The manifest should state property, dates, search type, dimensions, filters, data state, extraction version, represented coverage, and known limitations. This allows a reviewer to distinguish a changed search pattern from a changed query definition.
03
Failure cases
The most common failure is treating the API as a promise of every query row. It is not. Google says the Search Analytics method returns top rows and warns that detailed page or query dimensions may omit data. A pipeline that exports a polished table without this limitation is reproducible only in the sense that it can reproduce the same misunderstanding. [2]
A second failure is date drift. An extraction scheduled at midnight in Chicago, London, or UTC can request the wrong Search Console day if the job does not resolve Pacific Time explicitly. A third is mixing provisional and finalized data, then interpreting ordinary finalization changes as traffic volatility. A fourth is stopping pagination because one response contains fewer than 25,000 rows rather than continuing to the documented empty response.
Other failures include transforming before preserving raw data, changing filters without changing the dataset version, duplicating rows during reruns, swallowing quota errors as zero traffic, and comparing a detailed table with an aggregate total as though both had identical row coverage. Search Console is an observed reporting surface with defined aggregation and omission rules, not an unrestricted event warehouse.
The practical standard is modest but strict: save the request, save the response, preserve the time zone and data state, paginate according to the documented procedure, reconcile at a lower dimensionality, and disclose what the export cannot contain. That produces evidence suitable for analysis instead of a spreadsheet that merely arrived on schedule.
References
Sources behind this record
- Getting your performance data — Google Search Central (accessed August 2, 2026)
- Search Analytics: query — Google Search Central (accessed August 2, 2026)
- Search Console API usage limits — Google Search Central (accessed August 2, 2026)
- About Search Console data — Google Search Console Help (accessed August 2, 2026)
Corrections
Correction history
No corrections recorded.
To report an error, use the public corrections path.
The workflow cannot retrieve rows Google does not expose.
The API returns top rows rather than guaranteeing every row for highly detailed queries.
Current quotas, search-appearance values, and reporting surfaces can change.