Page Summary
-
To retrieve Google Ads API entities and reporting data, you can use either
GoogleAdsService.SearchStreamorGoogleAdsService.Search. -
While both methods are suitable for production and fetching objects and reports,
SearchStreamprovides a stream ofGoogleAdsRowobjects in a single continuous response, whereasSearchreturns pages ofGoogleAdsRowobjects over multiple responses. -
SearchStreamsends a single request and initiates a persistent connection, allowing data packets to download immediately and potentially offering improved performance for bigger reports compared to the paged requests ofSearch. -
For multiple page reports,
SearchStreamis typically faster thanSearchas it avoids multiple round trips. -
Daily limits for both methods are based on access levels, and a single query or report is counted as one operation regardless of whether it is paged or streamed.
To retrieve Google Ads API entities and reporting data, use one of these methods:
Here are the high-level distinctions for the two methods:
| GoogleAdsService.SearchStream | GoogleAdsService.Search | |
|---|---|---|
| Suitable for production code | Yes | Yes |
| Service | GoogleAdsService |
GoogleAdsService |
| Scenario | Fetching objects and reports | Fetching objects and reports |
| Response | Stream of GoogleAdsRow objects |
Pages of GoogleAdsRow objects |
| Response's fields | Only those specified in the query | Only those specified in the query |
| Daily limits | Daily limits based on access levels | Daily limits based on access levels |
SearchStream versus Search
While Search sends multiple paginated requests to
download an entire report, SearchStream sends
a single request and initiates a persistent gRPC connection with the Google Ads API
regardless of report size.
For SearchStream, data packets start to download immediately in batches of
SearchGoogleAdsStreamResponse objects. Your code can
iterate over incoming batches as they arrive without waiting for the entire
stream to finish.
By eliminating the round-trip network time required to request each individual
page of a Search response, SearchStream offers improved performance over
paging, especially for large reports.
Example
This example looks at a report that consists of 100,000 rows. The following
table breaks down the request and response differences between the two methods:
| SearchStream | Search | |
|---|---|---|
| Page size | Not Applicable | 10,000 rows per page |
| Number of API requests | 1 request | 10 requests |
| Number of API responses | 1 continuous stream | 10 responses |
Performance factors
For most use cases, we recommend SearchStream over Search for the following
reasons:
- Single-page reports (under 10,000 rows): There are no significant performance differences between the two methods.
- Multi-page reports:
SearchStreamis typically faster because multiple network round trips are avoided, and reading or writing from disk cache is less of a factor. - Memory efficiency: When processing large reports with
SearchStream, iterate through stream chunks and process rows as they arrive rather than buffering all rows in memory at once to avoid out-of-memory (OOM) errors. - Connection resiliency: Because
SearchStreamrelies on a persistent connection, long-running streams can be interrupted by network drops or deadline timeouts. Configure appropriate RPC timeouts and implement retry logic for transient stream errors.
Rate limits
Daily operation limits for both methods adhere to the standard limits and
access levels of your Google Cloud project. A single logical
report query is counted as one operation toward your daily operation quota
regardless of whether the result is streamed with SearchStream or retrieved
across multiple cached pages using Search with a page_token. However, each
paged Search request still counts as an individual RPC call against short-term
rate limits.
Code example
The following code example demonstrates how to execute a streaming report query using the client libraries:
Java
private void runExample(GoogleAdsClient googleAdsClient, long customerId) { try (GoogleAdsServiceClient googleAdsServiceClient = googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) { String query = "SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id"; // Constructs the SearchGoogleAdsStreamRequest. SearchGoogleAdsStreamRequest request = SearchGoogleAdsStreamRequest.newBuilder() .setCustomerId(Long.toString(customerId)) .setQuery(query) .build(); // Creates and issues a search Google Ads stream request that will retrieve all campaigns. ServerStream<SearchGoogleAdsStreamResponse> stream = googleAdsServiceClient.searchStreamCallable().call(request); // Iterates through and prints all of the results in the stream response. for (SearchGoogleAdsStreamResponse response : stream) { for (GoogleAdsRow googleAdsRow : response.getResultsList()) { System.out.printf( "Campaign with ID %d and name '%s' was found.%n", googleAdsRow.getCampaign().getId(), googleAdsRow.getCampaign().getName()); } } } }
C#
public void Run(GoogleAdsClient client, long customerId) { // Get the GoogleAdsService. GoogleAdsServiceClient googleAdsService = client.GetService( Services.V25.GoogleAdsService); // Create a query that will retrieve all campaigns. string query = @"SELECT campaign.id, campaign.name, campaign.network_settings.target_content_network FROM campaign ORDER BY campaign.id"; try { // Issue a search request. googleAdsService.SearchStream(customerId.ToString(), query, delegate (SearchGoogleAdsStreamResponse resp) { foreach (GoogleAdsRow googleAdsRow in resp.Results) { Console.WriteLine("Campaign with ID {0} and name '{1}' was found.", googleAdsRow.Campaign.Id, googleAdsRow.Campaign.Name); } } ); } catch (GoogleAdsException e) { Console.WriteLine("Failure:"); Console.WriteLine($"Message: {e.Message}"); Console.WriteLine($"Failure: {e.Failure}"); Console.WriteLine($"Request ID: {e.RequestId}"); throw; } }
PHP
public static function runExample(GoogleAdsClient $googleAdsClient, int $customerId) { $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient(); // Creates a query that retrieves all campaigns. $query = 'SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id'; // Issues a search stream request. /** @var GoogleAdsServerStreamDecorator $stream */ $stream = $googleAdsServiceClient->searchStream( SearchGoogleAdsStreamRequest::build($customerId, $query) ); // Iterates over all rows in all messages and prints the requested field values for // the campaign in each row. foreach ($stream->iterateAllElements() as $googleAdsRow) { /** @var GoogleAdsRow $googleAdsRow */ printf( "Campaign with ID %d and name '%s' was found.%s", $googleAdsRow->getCampaign()->getId(), $googleAdsRow->getCampaign()->getName(), PHP_EOL ); } }
Python
def main(client: GoogleAdsClient, customer_id: str) -> None: ga_service: GoogleAdsServiceClient = client.get_service("GoogleAdsService") query: str = """ SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id""" # Issues a search request using streaming. stream: Iterator[SearchGoogleAdsStreamResponse] = ga_service.search_stream( customer_id=customer_id, query=query ) for batch in stream: rows: List[GoogleAdsRow] = batch.results for row in rows: print( f"Campaign with ID {row.campaign.id} and name " f'"{row.campaign.name}" was found.' )
Ruby
def get_campaigns(customer_id) # GoogleAdsClient will read a config file from # ENV['HOME']/google_ads_config.rb when called without parameters client = Google::Ads::GoogleAds::GoogleAdsClient.new responses = client.service.google_ads.search_stream( customer_id: customer_id, query: 'SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id', ) responses.each do |response| response.results.each do |row| puts "Campaign with ID #{row.campaign.id} and name '#{row.campaign.name}' was found." end end end
Perl
sub get_campaigns { my ($api_client, $customer_id) = @_; # Create a search Google Ads stream request that will retrieve all campaigns. my $search_stream_request = Google::Ads::GoogleAds::V25::Services::GoogleAdsService::SearchGoogleAdsStreamRequest ->new({ customerId => $customer_id, query => "SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id" }); # Get the GoogleAdsService. my $google_ads_service = $api_client->GoogleAdsService(); my $search_stream_handler = Google::Ads::GoogleAds::Utils::SearchStreamHandler->new({ service => $google_ads_service, request => $search_stream_request }); # Issue a search request and process the stream response to print the requested # field values for the campaign in each row. $search_stream_handler->process_contents( sub { my $google_ads_row = shift; printf "Campaign with ID %d and name '%s' was found.\n", $google_ads_row->{campaign}{id}, $google_ads_row->{campaign}{name}; }); return 1; }