RankParse

Google Search Console

Query your own live Google Search Console data (queries, pages, countries, devices, sitemaps, URL inspection) through the RankParse API.

GET/v1/gsc/search-analyticsFreeAPI key + connected Google account

The /v1/gsc/* routes proxy the Google Search Console API for properties you have connected to RankParse. Every call is a live request to Google for one property, so the data is Google-only and exactly as fresh as Search Console itself. Google only returns finalized data, so the most recent day or two are typically missing.

Three separate data products, three separate endpoint families. Do not mix them up:

  • This page: live, Google-only Search Console data (queries, pages, countries, devices, sitemaps, URL inspection).
  • Rank tracking: stored, scheduled snapshots of Google, Bing and Yandex keyword rankings side by side.
  • Google Ads keyword research: search volume and competition for keywords. It never returns rankings.

Before you call

Connect Google Search Console

In the dashboard open Integrations, choose Google Search Console and click Connect. Sign in with a Google account that has access to the properties you want to query. You can connect more than one Google account; each property is read through the account that can see it.

List your properties

Call GET /v1/gsc/properties and copy a siteUrl exactly as it is returned. The site parameter on every other route must match it character for character (https://example.com/ with the trailing slash for a URL-prefix property, or sc-domain:example.com for a domain property).

Query it

Call GET /v1/gsc/search-analytics with site, startDate and endDate.

Authentication and cost

  • Send your API key in the X-API-Key header, as on every other endpoint. See Authentication.
  • The Google connection belongs to your workspace, not to the key. Any key in the workspace uses it.
  • All /v1/gsc/* routes cost 0 credits. They are limited only by the shared rate limit of 60 requests per minute per key (see Rate limiting) and by Google's own quotas.
  • The query routes (search-analytics, sitemaps, url-inspection) require a team role (owner, admin or member). A client-role member gets 403 capability_missing.
  • Responses are returned as plain objects. They are not wrapped in the usual data / credits_used envelope.

GET /v1/gsc/status

GET/v1/gsc/statusFreeAPI key

Reports whether a Google account is connected. It makes no call to Google and is not rate limited.

{
  "connected": true,
  "google_email": "you@example.com",
  "connected_at": 1756112400000,
  "connections": [
    { "id": "conn_abc123", "label": "you@example.com", "status": "active", "property_count": 4 }
  ]
}
FieldTypeDescription
connectedbooleantrue when at least one Google account is connected
google_emailstringAccount email. Omitted when not connected
connected_atintegerUnix time in milliseconds. Omitted when not connected
connectionsarrayEvery non-revoked Google connection of the workspace
connections[].statusstringactive, reauth_required (reconnect it in the dashboard) or revoked
connections[].property_countintegerProperties that connection can see

GET /v1/gsc/properties

GET/v1/gsc/propertiesFreeAPI key

Lists the Search Console properties visible to your connected Google account or accounts. When several accounts are connected, a property visible to more than one is listed once, at the highest permission level.

curl "https://api.rankparse.com/v1/gsc/properties" \
  -H "X-API-Key: rp_your_key"
import requests

res = requests.get(
    "https://api.rankparse.com/v1/gsc/properties",
    headers={"X-API-Key": "rp_your_key"},
)
print(res.json()["properties"])
const res = await fetch("https://api.rankparse.com/v1/gsc/properties", {
  headers: { "X-API-Key": "rp_your_key" },
});
const { properties } = await res.json();
{
  "properties": [
    { "siteUrl": "sc-domain:example.com", "permissionLevel": "siteOwner" },
    { "siteUrl": "https://example.com/", "permissionLevel": "siteFullUser" }
  ]
}

permissionLevel is Google's value for your access to the property (for example siteOwner, siteFullUser, siteRestrictedUser, siteUnverifiedUser).

GET /v1/gsc/search-analytics

GET/v1/gsc/search-analyticsFreeAPI key + connected Google account

Runs a Search Console performance query: clicks, impressions, click-through rate and average position, grouped by the dimensions you choose.

Parameters

ParameterTypeRequiredDefaultDescription
sitestringYesProperty URL exactly as returned by /v1/gsc/properties
startDatestringYesFirst day, YYYY-MM-DD
endDatestringYesLast day, YYYY-MM-DD
dimensionsstringNoqueryComma-separated list. Allowed: query, page, country, device, date, searchAppearance. Unknown names are dropped; if none are valid the call fails with invalid_dimensions
searchTypestringNowebOne of web, image, video, news, googleNews, discover
filterPagestringNoKeep rows whose page URL equals this exactly
filterPageContainsstringNoKeep rows whose page URL contains this text (for segments such as /blog/). Cannot be combined with filterPage
filterQuerystringNoKeep rows whose query equals this exactly
minPositionnumberNoKeep rows with average position at or above this
maxPositionnumberNoKeep rows with average position at or below this
maxCtrnumberNoKeep rows with CTR at or below this, as a fraction from 0 to 1 (0.03 means 3%)
minImpressionsnumberNoKeep rows with at least this many impressions
rowLimitintegerNo100Rows to return. Capped at 1000

Notes on the parameters:

  • RankParse checks only that dates look like YYYY-MM-DD. Google applies its own range rules (for example its limited history window), and a request Google rejects comes back as 502 gsc_api_error carrying Google's message.
  • filterPage and filterQuery can be used together. Both must match.
  • The order of keys in each row follows the order of dimensions that were accepted.
  • minPosition, maxPosition, maxCtr and minImpressions are applied by RankParse after Google responds. When any of them is set, RankParse fetches Google's top 1000 rows (Google orders by clicks, descending), filters them, then trims to rowLimit. A filter can therefore only find rows inside that top 1000. For a large property, narrow the date range or add filterPageContains first.

Example

Queries on positions 8 to 20 over the last month, the "quick win" zone:

curl -G "https://api.rankparse.com/v1/gsc/search-analytics" \
  -H "X-API-Key: rp_your_key" \
  --data-urlencode "site=https://example.com/" \
  --data-urlencode "startDate=2026-09-01" \
  --data-urlencode "endDate=2026-09-30" \
  --data-urlencode "dimensions=query" \
  --data-urlencode "minPosition=8" \
  --data-urlencode "maxPosition=20" \
  --data-urlencode "rowLimit=50"
import requests

res = requests.get(
    "https://api.rankparse.com/v1/gsc/search-analytics",
    headers={"X-API-Key": "rp_your_key"},
    params={
        "site": "https://example.com/",
        "startDate": "2026-09-01",
        "endDate": "2026-09-30",
        "dimensions": "query",
        "minPosition": 8,
        "maxPosition": 20,
        "rowLimit": 50,
    },
)
for row in res.json()["rows"]:
    print(row["keys"][0], row["position"], row["impressions"])
const params = new URLSearchParams({
  site: "https://example.com/",
  startDate: "2026-09-01",
  endDate: "2026-09-30",
  dimensions: "query",
  minPosition: "8",
  maxPosition: "20",
  rowLimit: "50",
});
const res = await fetch(`https://api.rankparse.com/v1/gsc/search-analytics?${params}`, {
  headers: { "X-API-Key": "rp_your_key" },
});
const { rows } = await res.json();

Response

{
  "site": "https://example.com/",
  "startDate": "2026-09-01",
  "endDate": "2026-09-30",
  "dimensions": ["query"],
  "searchType": "web",
  "rows": [
    {
      "keys": ["buy widgets online"],
      "clicks": 14,
      "impressions": 1320,
      "ctr": 0.0106,
      "position": 9.4
    }
  ],
  "responseAggregationType": "byProperty"
}

Response fields

FieldTypeDescription
site, startDate, endDatestringEcho of the request
dimensionsstring[]The dimensions that were accepted, in order
searchTypestringThe search type used
filterPage, filterPageContains, filterQuerystringEchoed back only when you sent them
rowsarrayResult rows, at most rowLimit
rows[].keysstring[]One value per dimension, in dimensions order (for date, a YYYY-MM-DD string)
rows[].clicksnumberClicks from Google Search
rows[].impressionsnumberImpressions in Google Search
rows[].ctrnumberClick-through rate as a fraction from 0 to 1
rows[].positionnumberAverage position for the row. A provider average, not a live SERP rank
responseAggregationTypestringHow Google aggregated the rows (byProperty, byPage, auto). Omitted if Google does not send it

An empty result is a 200 with "rows": [].

Common recipes

GoalRequest
Top queriesdimensions=query
Top pagesdimensions=page
Queries for one pagedimensions=query&filterPage=https://example.com/blog/post
Pages ranking for one querydimensions=page&filterQuery=best seo tools
Daily trenddimensions=date (use rowLimit=500 or more for long ranges)
Cannibalization checkdimensions=query,page
Low CTR, high impressionsdimensions=page&minImpressions=500&maxCtr=0.05
One section of the sitedimensions=page&filterPageContains=/blog/
Countries or devicesdimensions=country or dimensions=device
Rich result and search featuresdimensions=searchAppearance

GET /v1/gsc/sitemaps

GET/v1/gsc/sitemapsFreeAPI key + connected Google account

Lists the sitemaps submitted for a property, with Google's processing status.

ParameterTypeRequiredDescription
sitestringYesProperty URL exactly as returned by /v1/gsc/properties
curl -G "https://api.rankparse.com/v1/gsc/sitemaps" \
  -H "X-API-Key: rp_your_key" \
  --data-urlencode "site=https://example.com/"
{
  "site": "https://example.com/",
  "sitemaps": [
    {
      "path": "https://example.com/sitemap.xml",
      "lastSubmitted": "2026-08-01T10:12:44.000Z",
      "isPending": false,
      "isSitemapsIndex": false,
      "type": "sitemap",
      "lastDownloaded": "2026-09-28T04:30:12.000Z",
      "warnings": 0,
      "errors": 0,
      "contents": [{ "type": "web", "submitted": 412, "indexed": 398 }]
    }
  ]
}

Each sitemap object is Google's own record. path is always present; the other fields (lastSubmitted, isPending, isSitemapsIndex, type, lastDownloaded, warnings, errors, contents) appear when Google reports them. A property with no submitted sitemaps returns "sitemaps": [].

GET /v1/gsc/url-inspection

GET/v1/gsc/url-inspectionFreeAPI key + connected Google account

Returns Google's index status for one URL, using the Search Console URL Inspection API.

ParameterTypeRequiredDescription
sitestringYesProperty URL exactly as returned by /v1/gsc/properties. The inspected URL must belong to it
urlstringYesFull URL to inspect, for example https://example.com/blog/post
curl -G "https://api.rankparse.com/v1/gsc/url-inspection" \
  -H "X-API-Key: rp_your_key" \
  --data-urlencode "site=https://example.com/" \
  --data-urlencode "url=https://example.com/blog/post"
import requests

res = requests.get(
    "https://api.rankparse.com/v1/gsc/url-inspection",
    headers={"X-API-Key": "rp_your_key"},
    params={"site": "https://example.com/", "url": "https://example.com/blog/post"},
)
status = res.json()["inspectionResult"]["indexStatusResult"]
print(status["verdict"], status["coverageState"])
const params = new URLSearchParams({
  site: "https://example.com/",
  url: "https://example.com/blog/post",
});
const res = await fetch(`https://api.rankparse.com/v1/gsc/url-inspection?${params}`, {
  headers: { "X-API-Key": "rp_your_key" },
});
const { inspectionResult } = await res.json();
{
  "site": "https://example.com/",
  "url": "https://example.com/blog/post",
  "inspectionResult": {
    "inspectionResultLink": "https://search.google.com/search-console/inspect?resource_id=https://example.com/&id=abc",
    "indexStatusResult": {
      "verdict": "PASS",
      "coverageState": "Submitted and indexed",
      "robotsTxtState": "ALLOWED",
      "indexingState": "INDEXING_ALLOWED",
      "lastCrawlTime": "2026-09-27T06:14:00Z",
      "pageFetchState": "SUCCESSFUL",
      "googleCanonical": "https://example.com/blog/post",
      "userCanonical": "https://example.com/blog/post",
      "sitemap": ["https://example.com/sitemap.xml"],
      "crawledAs": "MOBILE"
    },
    "mobileUsabilityResult": { "verdict": "PASS" }
  }
}

The inspectionResult object is Google's. indexStatusResult carries verdict, coverageState, robotsTxtState, indexingState, pageFetchState and, when known, lastCrawlTime, googleCanonical, userCanonical, sitemap, referringUrls and crawledAs. ampResult, mobileUsabilityResult and richResultsResult are present when Google evaluates them for the page. Google applies its own URL Inspection quota per property; exceeding it returns 429 gsc_quota_exceeded.

Errors

All errors use the standard shape { "error", "code", "message" }. See Error codes.

StatusCodeMeaning
400gsc_not_connectedNo Google Search Console account is connected. Connect it under Dashboard, Integrations
400missing_sitesite is missing (search-analytics, sitemaps)
400missing_datesstartDate or endDate is missing
400invalid_dateA date is not in YYYY-MM-DD shape
400invalid_dimensionsNone of the requested dimensions is valid
400invalid_search_typesearchType is not one of the allowed values
400conflicting_filtersfilterPage and filterPageContains were both sent
400invalid_paramminPosition, maxPosition, maxCtr or minImpressions is not a number
400missing_paramssite or url is missing (url-inspection)
401invalid_api_keyMissing, invalid or revoked API key
401gsc_token_expiredThe Google connection expired or was revoked. Reconnect under Dashboard, Integrations
403capability_missingYour workspace role cannot run live provider queries
403gsc_access_deniedGoogle denied access to this property. Check the exact site value and that the property is verified for the connected account
404gsc_property_not_foundThe property is not visible to any connected Google account, or Google returned 404 for it
429rate_limitedMore than 60 requests per minute for this key
429gsc_quota_exceededGoogle's Search Console API quota was exceeded. Retry later
502gsc_token_refresh_failedRankParse could not refresh the Google access token. Retry shortly
502gsc_api_errorAny other upstream failure, including requests Google rejects. The message carries the upstream detail
503gsc_not_configuredThe Search Console integration is not configured on the server

MCP tools

These tools wrap the routes above. They are available on the API-key MCP endpoint (mcp.rankparse.com) only. The secure OAuth connector (connect.rankparse.com) does not include any Search Console tool. All are read-only and cost 0 credits. See MCP Server.

ToolPurpose
get_gsc_propertiesList connected Search Console properties
get_gsc_top_queriesTop queries by clicks
get_gsc_top_pagesTop pages by clicks
get_gsc_page_queriesQueries that drive traffic to one page
get_gsc_query_pagesPages that rank for one query
get_gsc_date_trendsDaily clicks, impressions, CTR and position for a range
get_gsc_country_breakdownTraffic by country
get_gsc_device_breakdownTraffic by device type
get_gsc_sitemapsSubmitted sitemaps and their status
get_gsc_url_inspectionIndex status of one URL
get_gsc_query_page_pairsQuery and page combinations, for spotting cannibalization
get_gsc_page_trendDaily trend for one page
get_gsc_query_trendDaily trend for one query
get_gsc_opportunity_queriesQueries at positions 8 to 20 (defaults), the quick-win zone
get_gsc_low_ctr_queriesHigh-impression queries with low CTR (defaults: at least 100 impressions, CTR at most 0.05)
get_gsc_low_ctr_pagesHigh-impression pages with low CTR (defaults: at least 500 impressions, CTR at most 0.05)
get_gsc_page_segmentTop pages inside a URL segment such as /blog/
get_gsc_search_appearanceTraffic split by search appearance (rich results, video, and so on)

On this page