Blog/Search & RAG
5 min read

Rank Tracking API: Track Keyword Positions Over Time

Track keyword positions with one API call per keyword, then store the position plus the parameters and page shape so the series stays comparable.

Rank Tracking API: Track Keyword Positions Over Time

Check where your domain ranks on Google for a keyword, with the parameters saved beside the number. Paste this into your agent:

Set up https://monid.ai/SKILL.md, and then use Monid to run a Google search for "best web scraping api" in the US, tell me which position thunderbit.com holds, and give me the position, the URL and the search parameters used as one row.

One prompt returns one row of a rank series. 1 min setup · 20-40 hrs saved.

You want to know where a page ranks for a keyword, today and every day after, without opening a dashboard. Getting one position is a single call. The harder part is the series: the same parameters on every run, a stored row you can read a year later, and a way to tell your move from the page changing under you. This guide shows the quickest way to pull positions into your agent or your own table, what two live runs returned on 2026-10-16, and what to store with each number. It runs through Monid, the OpenRouter for agent tools: one key, one balance, every tool priced per call.

What is the easiest way to get rank tracking data through an API?

Monid. Install it once, add a key, and your agent calls a Google results endpoint that returns a numbered position per result, with no plan to pick and no vendor account to open.

  • Pay per call. A Google results page costs $0.00015 on the endpoint we ran (Verified 2026-10-16 on the web search tools page). Buy calls as you need them: no monthly plan and no minimum top-up. Discovery and inspection are free; only a run bills.
  • One install, every tool. The same key and balance call the search endpoints and every other tool on Monid, so the page you investigate after a rank drop is one more call, not one more account.
  • Lives inside your agent. Install the CLI, add your key, run the prompt above, and the endpoint is there whenever your agent needs a position, with nothing to keep running. Your agent reads SKILL.md and learns the rest, so setup is about a minute.

There is no official Google API that returns the position of an arbitrary page for a keyword, which is why rank tracking runs through search-results endpoints like this one.

How do you track rankings for a keyword list on a schedule?

Run one search per keyword with the same parameters every time, take the position of your domain from the results, and write a row. Three steps, and the third decides whether the series is worth anything.

For agents

Grab an API key at app.monid.ai, then paste this to your agent and hand it the key:

set up https://monid.ai/SKILL.md

It learns the whole discover, inspect, run workflow itself. More in the agent quickstart.

For humans

npm install -g @monid-ai/cli
monid keys add -k <your-api-key> -l main

Step 1. Find an endpoint that returns a position

Not every search endpoint gives you a rank. Retrieval-oriented ones return their own relevance ordering, which says nothing about where Google put a page. Search the catalogue and read the schema, both free:

monid discover -q "google search results with positions"
monid inspect -p api.strale.io -e /x402/google-search
monid inspect -p litescrape -e /google/search

Check that an integer position exists in the description. The litescrape inspect text lists organic_results (position, title, link, displayed_link, snippet), which is what a tracker needs.

Step 2. Fetch with parameters you will repeat

monid run -p litescrape -e /google/search -w \
  --query '{"q": "best web scraping api", "gl": "us", "hl": "en", "device": "desktop", "num": 10}'

Pin country (gl), language (hl) and device explicitly instead of accepting defaults. The schema also takes location for a named city, google_domain, and start to page further down.

Step 3. Write the row, not the number

row = {
    "keyword": kw,
    "checked_at": now_utc(),
    "position": next((r["position"] for r in res["organic_results"]
                      if domain(r["link"]) == MY_DOMAIN), None),
    "organic_count": len(res["organic_results"]),
    "had_ai_overview": "ai_overview" in res,
    "params": res["search_parameters"],
    "run_id": run_id,
}

position is None when your domain is not on the page. That is different from position 100, and mixing them is the commonest mistake in homegrown trackers. Loop it over keywords.txt with a scheduler and you have the whole system; the loop pattern is in Automate SERP Tracking with a Structured Google Search API.

Give this to your agent

$Set up https://monid.ai/SKILL.md, and then use Monid to check where my domain ranks in the US for each keyword in this list, store the position, the organic result count, whether an AI Overview appeared and the search parameters, and tell me which keywords moved since the last run.

Can you build a rank tracker yourself with Python?

Yes, and for a handful of keywords it is a fair weekend. You send a request to Google, parse the HTML, find your domain, and save the number. It breaks the moment the page changes or the requests start being blocked, and rank checks are exactly the traffic that gets blocked, because they are repeated, scheduled and identical.

A tracker that survives needs a proxy or browser setup, location and device handling, a parser that follows layout changes, retries, and a repair every time Google restructures the page. The parsing is the part that keeps costing time: AI blocks, local packs, video rows and forum rows all sit between the organic results, and each change shifts what "position" means. Hours of setup come before the first trustworthy row, and upkeep never ends.

A call on Monid costs $0.00015 (Verified 2026-10-16), and the fetch, the localisation and the parsing are maintained for you. Pick Monid for anything you will run more than once and keep the Python for the part only you can write: the storage and the questions. Reading the raw page parameters Google accepts is a useful skill either way; Google search URL parameters covers them.

What does a rank record look like, and what can you build with it?

A rank record has three layers: the results, the page around them, and the run itself. We ran litescrape /google/search for "best web scraping api" with gl us, hl en, desktop and num 10 on 2026-10-16, so the fields below are what came back.

The results

Each entry in organic_results carried position, position_absolute, title, link, displayed_link, snippet, a date when Google showed one, and a small favicon. Trimmed:

{ "position": 5,
  "position_absolute": 5,
  "title": "11 Web Scraping APIs Compared Hands-On (2026)",
  "link": "https://thunderbit.com/blog/best-web-scraping-apis",
  "displayed_link": "https://thunderbit.com › blog › best-web-scraping-apis",
  "date": "Aug 18, 2026" }

The page around the results

The same response carried related_searches (9 entries), related_questions (4), discussions_and_forums (3 entries), inline_videos (3), an ai_overview block with text and references, search_information.total_results (102) and a pagination object. These are the shape of the page. A keyword whose AI Overview appears in March and disappears in June has changed enormously for you, and a table of integers shows a flat line across the event.

The run

search_parameters echoed q, device, google_domain, gl, hl, start and num, and search_metadata held a run id, a status, a created_at timestamp and the google_url that was fetched. Store search_parameters and the timestamp with every row: they are how you prove, a year later, that Monday and Thursday were comparable.

What you can build with it

  • A position column for a keyword list. One call per keyword per day, one row each, your domain's position or None.
  • A change feed. Diff each row against the previous one and send only the keywords that moved, which is the output a person wants on Monday morning. The history side of this is in AI visibility tracking: record the page's shape.
  • A competitor map. Keep every domain in organic_results, not only yours, and you can see who holds positions one to five for each keyword.

What goes wrong when you track rankings over time?

Three things hide until you have more than one run. Two of them showed up in our two calls on 2026-10-16.

Why did 10 results requested return 7?

Because num is a request, not a promise. The schema calls it a "best-effort first-page result count", and our run with num 10 returned 7 organic results, with a second run returning 8. A page also carries rows that are not organic, so a result count below the number you asked for is normal.

Store the count you got. organic_count in the row above costs nothing, and without it a missing position on a short page looks the same as a missing position on a full one.

Why did a second call disagree with the first?

We ran the same query with the same parameters a few seconds apart, the second time with fast_mode set to true, which returns organic results only. Positions 1, 3, 4 and 5 held the same URLs, including thunderbit.com at 5. Positions 2, 6 and 7 held different pages, and the second call returned 8 results against 7.

The only parameter we changed was fast_mode, and the endpoint echoes it in search_parameters. That is the point of storing the parameter object: two rows that differ in one flag are two different measurements, and a tracker that quietly alternates between modes produces moves that never happened. Pin every parameter, including the optional flags, and keep the object in the row.

Why does the data have no source field?

The litescrape response carries a run id and a created_at, but no field naming where the results came from. If you switch endpoint or provider mid-series, nothing in the payload tells you. Record the provider, the endpoint and the run id yourself in every row, and start a new series when you change any of them. Treat a provider switch as a break in the line, not as a ranking change.

How many calls is a keyword list?

One per keyword per check. 200 keywords checked daily for 30 days is 6,000 calls, which is $0.90 at $0.00015 a call (Verified 2026-10-16). Trim the list before you optimise anything else; the cost scales with keywords times days.

How do you track Bing rankings?

Use a Bing source, not a Google one. A position from a Google endpoint is a Google position, so a Bing series needs its own endpoint, its own parameters and its own stored row. Everything above applies unchanged: pin the market and device, store the parameter object, record the page shape, and treat an absent domain as None.

The official Bing Search API was retired, which removed the obvious way to read a Bing position programmatically; Bing Search API Retired: What Actually Replaces It covers what took its place. The endpoint walk-through, with the fields a Bing result carries, is in Bing SERP Tracker API: Track Bing Positions per Call.

For your own site, Bing Webmaster Tools reports performance data from Microsoft for properties you verify. Use it for the sites you control and a results endpoint for the ones you do not.

Which endpoint should I use for which job?

EndpointWhat it doesInputReturnsBillingPrice (Verified 2026-10-16)
litescrape/google/searchGoogle page as JSON, ran twiceq, gl, hl, device, num, location, fast_modeposition per organic result, AI Overview, related searchesPer call$0.00015
mrscraper/serp/googleGoogle results, inspectedquery, region, language, pageOrganic results with title, URL, description and relevancePer call$0.001
api.strale.io/x402/google-searchNumbered Google results, inspectedquery, country, language, num_resultsTitle, URL, snippet and positionPer call$0.1188
context.dev/web/searchRelevance-ranked results, inspectedquery, numResults, countryURL, title, relevancePer result$0.000253

Verified 2026-10-16 with monid inspect; the first row was run twice and the other three were inspected only. Current figures are on monid.ai/tools.

The billing column is the budget. Per-call endpoints make a month of rank checks a multiplication you can do before you start: keywords times days times the call price. At 6,000 checks a month that is $0.90 on the first row, $6.00 on the second and $712.80 on the third (Verified 2026-10-16), so the price of one call decides the project at this volume. Per-result billing, as on the last row, multiplies by the page size you request. context.dev/web/search returns a relevance band, not a Google position, so use it for retrieval and not for tracking.

When is another route a better fit?

You want the dashboard more than the data. Rank-tracking products ship charts, competitor overlays and client reports. If somebody needs to look at this weekly and does not want to build a chart, buy the chart. The storage argument here is about what the tool must do, not who should write it.

You need history you did not collect. A tracker you build starts today, and no schema gives you last year. Established tools keep archives, and if the question is what a keyword looked like before a past update, buying the archive is the only answer.

You only track your own site. Google Search Console reports average position across impressions for the sites you verify, free and first-party. It is an average over many queries and locations, not the position of one page at one moment, so it answers a different question, but for your own site it is the place to start.

Rank data is your product. If you resell positions, with device splits and the full SERP feature taxonomy, buy from a specialist whose product it also is.

And the disclosure: this is Monid's blog and Monid sells these endpoints. The most useful thing in this guide, storing the parameters and the page shape with every position, applies whoever you buy the data from.

Conclusion

The quickest way to track keyword positions is one search call per keyword through Monid: $0.00015 a call on the Google endpoint we ran (Verified 2026-10-16), one key for this and every other tool, about a minute to set up and ready inside your agent whenever you need a number. Writing your own scraper works for a few keywords and costs hours of proxies, parsing and upkeep.

Two things matter more than the choice of endpoint. Store the whole parameter object, including flags like fast_mode, because two calls with identical keywords and one different flag returned different pages on 2026-10-16. And store the page shape and the count of results you received, so a missing position can be told apart from a short page.

How we estimated the time saved: building a rank tracker yourself is roughly 10 to 20 hours for the fetch layer with proxies and parsing, 6 to 10 hours for the scheduler and the row schema, and 4 to 10 hours for the first month of upkeep. That is 20 to 40 hours. The 1 minute is the install, key and first call once you already have a Monid key.

Free next step: run monid discover -q "google search results with positions", then monid inspect -p litescrape -e /google/search, and make one call for a keyword you care about. Start at monid.ai.

FAQ

Is there a Google rank tracker API?

Google offers no API that returns the position of an arbitrary page for a keyword. Search Console reports average position for sites you verify, and for everything else you use a search-results endpoint with an integer position per result. Through Monid, litescrape/google/search is one, at $0.00015 a call (Verified 2026-10-16).

How do you track keyword rankings for free?

For your own site, Google Search Console is free and shows average position by query and page. For a specific keyword on a specific day, or for sites you do not own, a results endpoint is the route, and discovery and inspection on Monid cost nothing, so you can read every schema before you spend a cent.

What is the best keyword rank checker API?

The one that returns a numbered position, the parameters it ran under and a timestamp, at a billing shape you can calculate in advance. Per-call billing fixes the cost of a keyword-day, so the monthly figure is keywords times days times the call price. Rank checks with a relevance label instead of a position cannot be tracked.

How do you build a Google rank tracking API into a workflow?

Schedule the fetch, write the full row instead of the integer, and diff against the previous run. In a workflow tool such as n8n the same three steps apply, and the storage is the part the node will not solve for you.

Does location change the rank you get back?

Yes, and for anything with local intent it is the dominant variable. The litescrape/google/search schema takes gl for country, hl for language, location for a named place and device, and it echoes the ones you sent in search_parameters. Pin them explicitly and store what you pinned with every row.

Published August 2026.

rank tracking apiserp tracking apigoogle rank tracker apikeyword rank checker apibing rank tracker