RankParse

Google Ads keyword research

Search volume, competition and bid ranges from Google's Keyword Planner, for keyword ideas or a list you already have.

POST/v1/google-ads/keyword-ideasFree (daily caps apply)API key + connected Google Ads account

The /v1/google-ads/* routes expose Google Ads keyword planning for the Google Ads account you connect to RankParse. Use keyword-ideas to discover new keywords from seed terms or a page URL, and keyword-metrics to size a list of keywords you already have.

Volume and competition only, never rankings. Google Ads has no concept of organic search position. For "where do I rank?" use Google Search Console (live, Google only) or rank tracking (stored snapshots across Google, Bing and Yandex).

Manager (MCC) accounts are not supported yet. Keyword planning must target a regular Google Ads account. A login that only manages other accounts sees just its manager ID, and Google rejects keyword planning against it. Connect with a Google login that has direct access to a regular Ads account.

Before you call

Connect Google Ads

In the dashboard open Integrations, choose Google Ads and click Connect. Approve the Google consent screen with the Google login that can access your Ads account.

Choose an account

If your login can access exactly one Ads account, RankParse selects it for you. If it can access several, pick one from the Account dropdown on the Google Ads card. Keyword calls will not run until an account is selected (google_ads_no_account_selected).

Call the API

Send POST /v1/google-ads/keyword-ideas or POST /v1/google-ads/keyword-metrics with your API key.

Cost and daily caps

These routes cost 0 credits, so the daily caps below are the only limit on how much you can use them.

CapLimitError code
Per user, per UTC day100 requestsgoogle_ads_user_quota_exceeded
All RankParse users together, per UTC day10,000 requestsgoogle_ads_daily_quota_exceeded
  • Counting is per request, not per keyword. A keyword-metrics call with 200 keywords counts as one.
  • A request is counted only after Google answers it successfully. Failed calls do not use up your cap.
  • GET /v1/google-ads/accounts also calls Google and counts as one request.
  • Both caps reset at midnight UTC. The 429 body includes retry_after, the number of seconds until then.
  • Google enforces its own limit on top of these; hitting it returns google_ads_quota_exceeded.
  • Requests are also subject to the shared 60 requests per minute rate limit (see Rate limiting).

POST /v1/google-ads/keyword-ideas

POST/v1/google-ads/keyword-ideasFreeAPI key + connected Google Ads account

Discovers new keyword ideas from seed keywords, a URL, or both, each with average monthly searches, competition and top-of-page bid range.

Body parameters

Send JSON with Content-Type: application/json.

FieldTypeRequiredDefaultDescription
keywordsstring[]One of keywords or urlSeed keywords. Blank entries are ignored and only the first 20 are used
urlstringOne of keywords or urlA page or site URL to derive ideas from. If both keywords and url are sent, Google uses them together
languagestringNolanguageConstants/1000Google language resource name. 1000 is English. Must match languageConstants/<digits>
geo_target_constantsstring[]No["geoTargetConstants/2840"]Google location resource names. 2840 is the United States. Each must match geoTargetConstants/<digits>; only the first 10 are used
keyword_plan_networkstringNoGOOGLE_SEARCHGOOGLE_SEARCH or GOOGLE_SEARCH_AND_PARTNERS. Any other value falls back to the default
include_adult_keywordsbooleanNofalseInclude adult keywords. Only a literal true turns it on
limitintegerNoGoogle decidesMaximum ideas to return. Clamped to 1 to 1000

language and geo_target_constants are Google resource names, not bare IDs. Sending "2840" instead of "geoTargetConstants/2840" fails fast with a 400 and does not touch your cap. Google publishes the full lists of language and geo target IDs.

Example

curl -X POST "https://api.rankparse.com/v1/google-ads/keyword-ideas" \
  -H "X-API-Key: rp_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "keywords": ["seo api", "backlink checker"],
    "geo_target_constants": ["geoTargetConstants/2840"],
    "language": "languageConstants/1000",
    "limit": 25
  }'
import requests

res = requests.post(
    "https://api.rankparse.com/v1/google-ads/keyword-ideas",
    headers={"X-API-Key": "rp_your_key"},
    json={
        "keywords": ["seo api", "backlink checker"],
        "geo_target_constants": ["geoTargetConstants/2840"],
        "language": "languageConstants/1000",
        "limit": 25,
    },
)
for idea in res.json()["data"]:
    print(idea["keyword"], idea["metrics"]["avg_monthly_searches"])
const res = await fetch("https://api.rankparse.com/v1/google-ads/keyword-ideas", {
  method: "POST",
  headers: {
    "X-API-Key": "rp_your_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    keywords: ["seo api", "backlink checker"],
    geo_target_constants: ["geoTargetConstants/2840"],
    language: "languageConstants/1000",
    limit: 25,
  }),
});
const { data } = await res.json();

Response

{
  "data": [
    {
      "keyword": "seo api",
      "metrics": {
        "avg_monthly_searches": 1900,
        "competition": "MEDIUM",
        "competition_index": 47,
        "low_top_of_page_bid_micros": 1850000,
        "high_top_of_page_bid_micros": 6200000
      }
    }
  ],
  "total": 1,
  "total_available": 312,
  "customer_id": "1234567890"
}

Response fields

FieldTypeDescription
dataarrayKeyword ideas
data[].keywordstringThe keyword text
data[].metricsobjectMetrics for that keyword (see below)
totalintegerIdeas in this response
total_availableinteger or nullTotal ideas Google found, which can be larger than total
customer_idstringThe Google Ads account the call ran against

POST /v1/google-ads/keyword-metrics

POST/v1/google-ads/keyword-metricsFreeAPI key + connected Google Ads account

Returns metrics for an explicit list of keywords, with no expansion into related terms.

Body parameters

FieldTypeRequiredDefaultDescription
keywordsstring[]YesKeywords to look up. Blank entries are ignored. At most 200 are used; the rest are dropped and truncated is set to true
languagestringNolanguageConstants/1000Same as for keyword ideas
geo_target_constantsstring[]No["geoTargetConstants/2840"]Same as for keyword ideas (max 10)
keyword_plan_networkstringNoGOOGLE_SEARCHGOOGLE_SEARCH or GOOGLE_SEARCH_AND_PARTNERS
include_adult_keywordsbooleanNofalseOnly a literal true turns it on

Example

curl -X POST "https://api.rankparse.com/v1/google-ads/keyword-metrics" \
  -H "X-API-Key: rp_your_key" \
  -H "Content-Type: application/json" \
  -d '{"keywords": ["seo api", "rank tracker"]}'
import requests

res = requests.post(
    "https://api.rankparse.com/v1/google-ads/keyword-metrics",
    headers={"X-API-Key": "rp_your_key"},
    json={"keywords": ["seo api", "rank tracker"]},
)
body = res.json()
if body["truncated"]:
    print(f"Only the first {body['max_keywords']} keywords were looked up")
const res = await fetch("https://api.rankparse.com/v1/google-ads/keyword-metrics", {
  method: "POST",
  headers: {
    "X-API-Key": "rp_your_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ keywords: ["seo api", "rank tracker"] }),
});
const { data, truncated } = await res.json();

Response

{
  "data": [
    {
      "keyword": "seo api",
      "close_variants": ["seo apis"],
      "metrics": {
        "avg_monthly_searches": 1900,
        "competition": "MEDIUM",
        "competition_index": 47,
        "low_top_of_page_bid_micros": 1850000,
        "high_top_of_page_bid_micros": 6200000
      }
    }
  ],
  "total": 1,
  "requested": 2,
  "truncated": false,
  "max_keywords": 200,
  "customer_id": "1234567890"
}

Response fields

FieldTypeDescription
dataarrayOne entry per keyword Google returned metrics for
data[].keywordstringThe keyword text
data[].close_variantsstring[]Close variants Google groups with this keyword. Empty when none
data[].metricsobjectMetrics for that keyword (see below)
totalintegerEntries in data
requestedintegerKeywords actually sent to Google, after trimming to 200
truncatedbooleantrue when you sent more than 200 keywords. Treat the missing ones as "not asked for", not "no data"
max_keywordsintegerThe per-call limit (200)
customer_idstringThe Google Ads account the call ran against

The metrics object

FieldTypeDescription
avg_monthly_searchesinteger or nullAverage monthly searches. Google may report heavily rounded figures for accounts without meaningful ad spend, and the response does not say whether a figure is precise
competitionstring or nullGoogle's competition level for paid placement, for example LOW, MEDIUM or HIGH
competition_indexinteger or nullCompetition on a 0 to 100 scale
low_top_of_page_bid_microsinteger or nullLow end of the top-of-page bid range, in micros of the account currency (1,000,000 micros is one currency unit)
high_top_of_page_bid_microsinteger or nullHigh end of the top-of-page bid range, in the same units

Any metric can be null when Google does not return it. A per-month volume breakdown is not included.

GET /v1/google-ads/status

GET/v1/google-ads/statusFreeAPI key

Shows whether Google Ads is connected and which account is selected. It makes no call to Google, does not count against your daily cap and has no MCP tool.

{
  "connected": true,
  "google_email": "you@example.com",
  "connected_at": 1756112400000,
  "selected_customer_id": "1234567890",
  "login_customer_id": null
}

When nothing is connected the response is { "connected": false }. selected_customer_id is null while no account is chosen. login_customer_id is reserved for manager-account support and is currently always null.

GET /v1/google-ads/accounts

GET/v1/google-ads/accountsFreeAPI key

Lists the Google Ads accounts the connected Google login can access directly, as 10-digit customer IDs. It works before an account has been selected, and counts as one request against your daily cap.

{
  "data": ["1234567890", "9876543210"],
  "total": 2
}

An empty list means Google returned no directly accessible accounts for this login.

Errors

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

StatusCodeMeaning and fix
400invalid_jsonThe request body is not valid JSON
400missing_seedkeyword-ideas needs keywords and/or url
400missing_keywordskeyword-metrics needs a non-empty keywords array
400invalid_languagelanguage is not a resource name like languageConstants/1000
400invalid_geo_targetgeo_target_constants is not an array of names like geoTargetConstants/2840
400google_ads_not_connectedGoogle Ads is not connected. Connect it under Dashboard, Integrations
400google_ads_no_account_selectedConnected, but no Ads account is selected. Choose one on the Google Ads card
400google_ads_invalid_requestGoogle rejected the request, usually because of an invalid language or location. The message carries Google's detail
401invalid_api_keyMissing, invalid or revoked API key
401google_ads_token_expiredThe Google Ads connection expired or was revoked. Reconnect under Dashboard, Integrations
403capability_missingYour workspace role cannot use this route
403google_ads_developer_token_not_approvedRankParse's Google Ads developer token is not yet approved for live keyword data. Nothing is wrong with your account; this is pending on the RankParse side
403google_ads_customer_not_enabledThe selected Ads account is not active (never fully set up, or deactivated). Select a different account or activate this one in Google Ads
403google_ads_access_deniedGoogle denied the request. Most often the selected account is a manager (MCC) account. Select a regular Ads account
404google_ads_account_not_foundThe selected account was not found. Select it again on the Google Ads card
429rate_limitedMore than 60 requests per minute for this key
429google_ads_user_quota_exceededYou used your 100 requests for the UTC day. See retry_after
429google_ads_daily_quota_exceededRankParse's shared daily budget is used up. Try again after midnight UTC
429google_ads_quota_exceededGoogle's own Ads API quota was exceeded. Retry later
502google_ads_token_refresh_failedCould not refresh the Google access token. Retry shortly
502google_ads_api_errorAny other upstream failure
503google_ads_not_configuredThe Google Ads integration is not configured on the server

MCP tools

Available on the API-key MCP endpoint (mcp.rankparse.com) only, not on the secure OAuth connector. All are read-only and cost 0 credits, and every description tells the agent that results are volume and competition, not rankings. See MCP Server.

ToolPurpose
get_google_ads_accountsList accessible Google Ads accounts, to help pick one
get_google_ads_keyword_ideasDiscover new keywords from seeds and/or a URL, with volume, competition and bid ranges
get_google_ads_keyword_metricsVolume, competition and bid ranges for a specific list of keywords

The tools accept language, geo_target_constants and keyword_plan_network like the REST routes. include_adult_keywords is accepted by get_google_ads_keyword_ideas only.

On this page