You can page through results retrieved with
[`GoogleAdsService.Search`](https://developers.google.com/google-ads/api/reference/rpc/v26/GoogleAdsService/Search) instead of downloading the entire result
set at once. For an overview of reporting with the Google Ads API, see the
[Reporting overview](https://developers.google.com/google-ads/api/docs/reporting/overview).

> [!NOTE]
> **Note:** To retrieve large datasets efficiently over a single persistent connection without managing page tokens, use [`GoogleAdsService.SearchStream`](https://developers.google.com/google-ads/api/docs/reporting/streaming) instead of `Search`.

`Search` returns fixed pages of up to 10,000 rows. Setting `page_size` in
[`SearchGoogleAdsRequest`](https://developers.google.com/google-ads/api/reference/rpc/v26/SearchGoogleAdsRequest) is deprecated and returns a
[`RequestError.PAGE_SIZE_NOT_SUPPORTED`](https://developers.google.com/google-ads/api/reference/rpc/v26/RequestErrorEnum.RequestError#page_size_not_supported) error.

## Example query and pagination

Consider the following query:

    SELECT
      ad_group.id,
      ad_group_criterion.type,
      ad_group_criterion.criterion_id,
      ad_group_criterion.keyword.text,
      ad_group_criterion.keyword.match_type
    FROM ad_group_criterion
    WHERE ad_group_criterion.type = KEYWORD

If your account contains 50,000 keywords, the result set contains 10,000
[`GoogleAdsRow`](https://developers.google.com/google-ads/api/reference/rpc/v26/GoogleAdsRow) objects in the first response, along with a
[`next_page_token`](https://developers.google.com/google-ads/api/reference/rpc/v26/SearchGoogleAdsResponse#next_page_token).

To retrieve the next 10,000 rows, send the request again, but update the
request's `page_token` to the response's [`next_page_token`](https://developers.google.com/google-ads/api/reference/rpc/v26/SearchGoogleAdsResponse#next_page_token):

    {
      "query": "SELECT ad_group.id, ad_group_criterion.type, ad_group_criterion.criterion_id, ad_group_criterion.keyword.text, ad_group_criterion.keyword.match_type FROM ad_group_criterion WHERE ad_group_criterion.type = KEYWORD",
      "pageToken": "CN3q9...example_token..."
    }

Note that [`next_page_token`](https://developers.google.com/google-ads/api/reference/rpc/v26/SearchGoogleAdsResponse#next_page_token) is not populated in the response that
contains the last batch of rows.

Our client libraries handle paging automatically. You only have to iterate
through the rows of the response. When all rows in the current page have been
returned, the client library fetches a new page of rows automatically on your
behalf until the entire dataset is retrieved. If using REST instead of gRPC, you
must explicitly make a request for each new page.

## Caching and page token expiration

The Google Ads API internally caches the dataset so that subsequent page requests are
faster than the initial request. Note that `next_page_token` values have a
limited time to live (TTL) and expire if not used within a short period (around
two hours). If a page token expires, the API returns an error and you must start
a new query.

Your query must remain identical in subsequent requests to take advantage of the
cached data. Subsequent paged requests don't count as additional operations
toward your daily operation quota for [Explorer access](https://developers.google.com/google-ads/api/docs/api-policy/access-levels#explorer-access) and
[Basic access](https://developers.google.com/google-ads/api/docs/api-policy/access-levels#basic-access). If the query differs and is sent along with the
same page token, an error is returned.

> [!IMPORTANT]
> **Key Point:** If you need manual paging, such as for custom web pagination, we recommend that you retrieve and store the results locally, such as in a database, and build your own pagination logic.