Query your Google Search analytics data

  • Run queries to analyze your Google Search data, including search appearances, queries used, and device types, to enhance your property's search performance.

  • Discover how search traffic evolves, its origins, and the queries driving property visibility, along with insights for mobile targeting based on smartphone queries.

  • Identify high and low-performing pages in Google Search results based on click-through rates and access all data available within the Search Console Performance report.

  • Utilize the searchanalytics.query() method to access and analyze data, ensuring initial data presence verification within the desired timeframe for accurate results.

  • Retrieve data in batches for queries exceeding 25,000 rows, incrementing the start row for subsequent requests to access the entire dataset.

You can run queries over your Google Search data to see how often your property appears in Google Search results, with what queries, whether from desktop or smartphones, and much more. You can use the results to improve your property's search performance, for example:

  • See how your search traffic changes over time, where it's coming from, and what search queries are most likely to show your property.
  • Learn which queries are made on smartphones, and use this to improve your mobile targeting.
  • See which pages have the highest (and lowest) click-through rate from Google search results.

Search query data is exposed using the searchanalytics.query() method. The query() method exposes all the data available in the Performance report in Search Console. Before running any queries, you should read the Performance report documentation to learn what data is exposed and what it means.

This page shows how to perform common queries with different request parameters.

Getting started

Verify the presence of data

Before running a query, you should first test for the presence of data in that time range. Omit filters, sorting, row limits, and any other parameters except start date, end date, and "date" as the only dimension.

Code

request = {
 'startDate': flags.start_date,
 'endDate': flags.end_date,
 'dimensions': ['date']
 }

Output

python search_analytics_api_sample.py 'https://www.example.com/' '2015-05-01' '2015-05-15'
Available dates:
Keys Clicks Impressions CTR Position
2015年05月01日 22823.0 373911.0 0.0610385893969 8.1829472789
2015年05月02日 16075.0 299718.0 0.0536337490574 8.14173322924
2015年05月03日 18794.0 337759.0 0.055643224903 8.07772405769
2015年05月04日 31894.0 468076.0 0.0681385074219 7.4104611217
2015年05月05日 34392.0 482919.0 0.071216912153 7.20689805123
2015年05月06日 35650.0 484353.0 0.0736033430164 7.11683214515
2015年05月07日 33994.0 465812.0 0.0729779395979 6.91755472165
2015年05月08日 27328.0 413007.0 0.0661683700276 7.22172747677
2015年05月09日 16637.0 297302.0 0.0559599329974 8.01876206685
2015年05月10日 19167.0 332607.0 0.0576265682923 7.87882696395
2015年05月11日 35358.0 499888.0 0.070731843933 7.11701821208
2015年05月12日 35952.0 486583.0 0.073886675038 6.80677294521
2015年05月13日 34417.0 480777.0 0.071586203167 6.86552185317
2015年05月14日 32029.0 457187.0 0.0700566726525 6.92575904389
2015年05月15日 27071.0 415973.0 0.0650787430915 7.27105605412

Try different dates

We see that we have data for that segment of time, so it's safe to move forward. It's important to do this before running your actual query. For example, running this same query for a different range returns this:

python search_analytics_api_sample.py 'https://www.example.com/' '2015-06-01' '2015-06-15'
Available dates:
Keys Clicks Impressions CTR Position
2015年06月01日 31897.0 468486.0 0.0680852789624 6.81207122518
2015年06月02日 32975.0 460266.0 0.0716433540605 6.62655942433
2015年06月03日 32779.0 459599.0 0.0713208688444 6.58126758326
2015年06月04日 30116.0 435308.0 0.0691831990223 6.71409668557
2015年06月05日 25188.0 380444.0 0.0662068530454 7.00998570092
2015年06月06日 14829.0 272324.0 0.0544535186028 7.6309910254
2015年06月07日 17896.0 318094.0 0.056260099216 7.56606223318
2015年06月08日 33377.0 487274.0 0.0684973957158 6.77552260125
2015年06月09日 33885.0 484241.0 0.0699754874123 6.70545451542
2015年06月10日 32622.0 466250.0 0.0699667560322 6.64417372654
2015年06月11日 31317.0 447306.0 0.0700124746818 6.61534832978
2015年06月12日 25932.0 393791.0 0.065852190629 7.15718998149
2015年06月13日 15451.0 275493.0 0.0560849095984 7.69994518917
2015年06月14日 18358.0 318193.0 0.0576945438775 7.34048517724

Look carefully, and you'll notice that the data ends on the 14th; no data for the 15th.

You might find it useful to use the APIs explorer in free-form edit mode to test your queries quickly (click the dropdown arrow on the side of the request body field and click "Freeform editor").

After you've verified the range of valid dates, you can start grouping by other dimensions, adding filters, row count limits, and so on:

Top 10 queries, sorted by click count, descending

Code

request = {
 'startDate': flags.start_date,
 'endDate': flags.end_date,
 'dimensions': ['query'],
 'rowLimit': 10
}

Output

Top Queries:
Keys Clicks Impressions CTR Position
seo 3523.0 270741.0 0.0130124362398 5.86615252215
hreflang 3207.0 5496.0 0.583515283843 1.10080058224
robots.txt 2650.0 23005.0 0.115192349489 4.30367311454
301 redirect 2637.0 7814.0 0.337471205529 1.621192731
googlebot 2572.0 6421.0 0.400560660333 1.15823080517
google seo 2260.0 11205.0 0.201695671575 1.38295403838
google sitemap 1883.0 4288.0 0.439132462687 1.21175373134
canonical url 1882.0 3714.0 0.506731287022 1.12762520194
sitemap 1453.0 22982.0 0.06322339222 3.78074144983

Top 10 pages, sorted by click count, descending

Code

request = {
 'startDate': flags.start_date,
 'endDate': flags.end_date,
 'dimensions': ['page'],
 'rowLimit': 10
}

Output

Top Pages:
Keys Clicks Impressions CTR Position
https://www.example.com/21 10538.0 62639.0 0.168233847922 3.63031019014
https://www.example.com/65 9740.0 82375.0 0.118239757208 5.61003945372
https://www.example.com/15 9220.0 128101.0 0.0719744576545 5.32300294299
https://www.example.com/41 8859.0 426633.0 0.0207649197319 1.62309057199
https://www.example.com/53 8791.0 829679.0 0.0105956641062 14.4941887164
https://www.example.com/46 7390.0 82303.0 0.0897901656076 5.7723290767
https://www.example.com/27 7169.0 64013.0 0.111992876447 4.98709637105
https://www.example.com/80 6047.0 84233.0 0.0717889663196 4.10592048247
https://www.example.com/9 5886.0 59704.0 0.0985863593729 4.0897594801
https://www.example.com/8 5043.0 66869.0 0.0754161120998 4.57651527614

Top 10 queries in India, sorted by click count, descending

Note that the filter operator "equals" is omitted, as it is the default operator.

Code

request = {
 'startDate': flags.start_date,
 'endDate': flags.end_date,
 'dimensions': ['query'],
 'dimensionFilterGroups': [{
 'filters': [{
 'dimension': 'country',
 'expression': 'ind'
 }]
 }],
 'rowLimit': 10
 }

Output

Top queries in India:
Keys Clicks Impressions CTR Position
googlebot 250.0 429.0 0.582750582751 1.0
search console 238.0 34421.0 0.00691438366114 1.00101682113
dns error 189.0 850.0 0.222352941176 1.38470588235
google seo 165.0 552.0 0.298913043478 1.04166666667
canonical url 141.0 282.0 0.5 1.0
301 redirect 132.0 557.0 0.236983842011 1.78276481149
google search console 126.0 16898.0 0.00745650372825 1.03929459108
robots.txt 117.0 1046.0 0.111854684512 3.9206500956
canonical tag 111.0 223.0 0.497757847534 1.0

Top 10 mobile queries in India, sorted by click count, descending

Code

request = {
 'startDate': flags.start_date,
 'endDate': flags.end_date,
 'dimensions': ['query'],
 'dimensionFilterGroups': [{
 'filters': [{
 'dimension': 'country',
 'expression': 'ind'
 }, {
 'dimension': 'device',
 'expression': 'MOBILE'
 }]
 }],
 'rowLimit': 10
}

Output

Top mobile queries in India:
Keys Clicks Impressions CTR Position
search console 26.0 1004.0 0.0258964143426 1.00298804781
dns error 24.0 111.0 0.216216216216 1.27927927928
google seo 18.0 69.0 0.260869565217 1.02898550725
eliminar 16.0 134.0 0.119402985075 1.0
googlebot 11.0 24.0 0.458333333333 1.0
404 9.0 214.0 0.0420560747664 8.64018691589
robots.txt 9.0 40.0 0.225 4.025
google search console 8.0 438.0 0.0182648401826 1.04337899543
seo 8.0 111.0 0.0720720720721 4.96396396396

Query a slice of rows

You can query for a specific slice of rows by specifying a (zero-based) start row number and the number of rows to return. Specifying an invalid start row number will return an error, but specifying more rows than are available will return all available rows.

Top 11-20 mobile queries for the date range, sorted by click count, descending

Code

request = {
 'startDate': flags.start_date,
 'endDate': flags.end_date,
 'dimensions': ['query'],
 'dimensionFilterGroups': [{
 'filters': [{
 'dimension': 'device',
 'expression': 'mobile'
 }]
 }],
 'rowLimit': 10,
 'startRow': 10
 }

Output

Top 11-20 Mobile Queries:
Keys Clicks Impressions CTR Position
dns error 1220.0 15064.0 0.0809877854 3.13448726206
google seo 1161.0 7923.0 0.146535403 2.31479556195
sitemap 926.0 12478.0 0.0742106107 5.8130025067
googlebot 903.0 7822.0 0.115443621 4.6910285792
robots.txt 799.0 24868.0 0.0321296445 5.92759215963
404 520.0 12777.0 0.0406981295 5.80352636506
seo 506.0 2925.0 0.172991453 2.50413960996
search console 487.0 981.0 0.496432212 1.00036102455
canonical url 326.0 4087.0 0.0797651089 3.23664971157
301 redirect 261.0 3165.0 0.082464455 3.63074363869

Getting more than 25,000 rows

If your query has more than 25,000 rows of data, you can request data in batches of 25,000 rows at a time by sending multiple queries and incrementing the startRow value each time. Count the number of retrieved rows; if you get less than the number of rows requested, you have retrieved all the data. If your request ends exactly on the data boundary (for example, there are 25,000 rows and you requested startRow=0 and rowLimit=25000), on your next call you will get an empty response.

Top 1-25,000 mobile queries for the date range, sorted by click count, descending

Code

request = {
 'startDate': flags.start_date,
 'endDate': flags.end_date,
 'dimensions': ['query'],
 'dimensionFilterGroups': [{
 'filters': [{
 'dimension': 'device',
 'expression': 'mobile'
 }]
 }],
 'rowLimit': 25000,
 'startRow': 0
 }

Top 25,001-50,000 mobile queries for the date range, sorted by click count, descending

Code

request = {
 'startDate': flags.start_date,
 'endDate': flags.end_date,
 'dimensions': ['query'],
 'dimensionFilterGroups': [{
 'filters': [{
 'dimension': 'device',
 'expression': 'mobile'
 }]
 }],
 'rowLimit': 25000,
 'startRow': 25000
 }

Getting all your data

See Query all your search traffic.

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025年08月28日 UTC.