All articles

Build a Keyword Rank Tracker in Python Using Google SERP API (Free Tool)

Published Date Mar 2, 2026
Read 12 min
Build a Keyword Rank Tracker in Python Using Google SERP API (Free Tool)

TL;DR

  • Build a Python-based keyword rank tracker using Scrapingdog’s Google SERP API , no need for expensive SEO tools.

  • Fetch live Google results, scan top 100 positions, and capture your domain’s exact ranking.

  • Save results with dates in a CSV file to create historical ranking trends.

  • Automate daily runs and email reports for hands-free SEO monitoring.

  • Track both your site and competitors across different countries at a low cost.

If you’re into SEO or part of a marketing team, you’re likely familiar with rank-tracking tools. I am sure you might use tools like Semrush, Ahref, or something similar, but they are too expensive.

In this tutorial, we will create our rank-tracking tool with Scrapingdog’s Google SERP API and Python.

The video below shows the complete Python workflow step by step, from API request to rank tracking output.

Why Rank Tracking Matters for SEO

Most SEO tools tell you what keywords you could rank for. Rank tracking tells you what’s actually happening, and there’s a big difference.

When you publish a page, optimize a title tag, or build backlinks, you have no way of knowing if any of it worked unless you’re watching your rankings. Rank tracking is that feedback loop. Without it, you’re doing SEO blind.

Rankings Change Without Warning

Search rankings are not static. A keyword you ranked #4 for last month might be #11 today because a competitor published a better article or Google rolled out an update. Organic traffic lags behind ranking changes by days or weeks; by the time you notice a drop in Analytics, you’ve already lost ground. Daily rank tracking lets you catch these shifts early.

You Need to Track Competitors Too

Your ranking doesn’t exist in isolation. If a competitor jumps from #8 to #3 on a keyword you care about, you need to know that. A rank tracker lets you monitor any domain on any keyword, so you always know where you’re winning and where you’re losing ground.

Validate What’s Actually Working

Every time you make an on-page change, rewriting a title, improving content depth, adding internal links, and rank tracking are how you confirm whether it worked. Without it, every SEO decision is based on instinct. With it, you start building a playbook of what actually moves the needle for your site.

Why Build Your Own?

Tools like Semrush and Ahrefs are great, but expensive, $100–$500/month is hard to justify if you’re tracking a handful of keywords. Building your own tracker in Python using Scrapingdog’s Google SERP API gives you the same core data at a fraction of the cost, with full control over scheduling, storage, and logic.

Logic for Building a Keyword Position Tracker

To build a rank-tracking tool, we will need access to live organic Google search results data. If you’re unsure how this works, check this guide on scraping Google search results. We can get this data from the Google Search API, and once we have it, we can determine the rank of any website for any keyword with a simple GET request.

However, a target website might not always rank on the first page of Google results. This is where pagination becomes essential. Google typically displays 10 results per page, so if a website ranks beyond position 10, we need to paginate through multiple pages to find it. By incrementing the page parameter in our API request, we can crawl deeper into the search results. Checking page 2, page 3, and beyond until we either find the target domain or reach a predefined search depth limit (e.g., top 100 results or 10 pages).

This approach ensures accurate rank tracking even for keywords where the website ranks lower, while also keeping API usage efficient by stopping the search as soon as the target URL is found.

Prerequisite

  • We will need a trial account on Scrapingdog.

  • Python should be pre-installed on your machine. If it is not installed, then you can download it from here.

Now, start by creating a project folder; you can name it anything you like. This is where we’ll store our Python script and the scraped data.

1mkdir tracker
2cd tracker

Next, install the required libraries. We’ll use requests to make GET requests to ScrapingDog’s Google Search API, and pandas to organize and export the results (more on that shortly).

1pip install requests pandas

Once the dependencies are installed, create a new Python file inside the folder. For this tutorial, we’ll call it rank.py.

1touch rank.py

Now let’s start coding.

How to build a SERP rank checker in Python?

Before writing any code, make sure you have your Scrapingdog API key ready. If you don’t have one yet, you can grab the key from the dashboard.

1import requests
2import pandas as pd
3
4keywords = ['web scraping api', 'web scraping tool', 'google web scraping', 'best serp api', 'google scraping api']
5api_key = "your-api-key"
6url = "https://api.scrapingdog.com/google/"
7
8for keyword in keywords:
9 for page in range(0, 10): # pages 0-9 = top 100 results
10 params = {
11 "api_key": api_key,
12 "query": keyword,
13 "country": "us",
14 "page": page
15 }
16 response = requests.get(url, params=params)
17
18 if response.status_code == 200:
19 data = response.json()
20 print(data)
21 else:
22 print(f"Request failed for '{keyword}' page {page}: {response.status_code}")

We store our target keywords in a list and loop through each one. Since Google now returns 10 results per page, we loop through pages 0–9 to cover the top 100 results. The page parameter is zero-indexed, so page=0 is the first page, page=1 is the second, and so on.

Note: The country parameter lets you track rankings for any specific market. Change "us" to "gb", "in", "au" etc. to track rankings in different countries.

Now let’s actually extract the ranking data from the response:

1import requests
2import pandas as pd
3
4results = []
5target_domain = "scrapingdog.com" # Change this to your domain
6
7keywords = ['web scraping api', 'web scraping tool', 'google web scraping', 'best serp api', 'google scraping api']
8api_key = "your-api-key"
9url = "https://api.scrapingdog.com/google/"
10
11for keyword in keywords:
12 found = False
13
14 for page in range(0, 10): # pages 0-9 = top 100 results
15 if found:
16 break # No need to check further pages once domain is found
17
18 params = {
19 "api_key": api_key,
20 "query": keyword,
21 "country": "us",
22 "page": page
23 }
24 response = requests.get(url, params=params)
25
26 if response.status_code == 200:
27 data = response.json()
28 organic = data.get('organic_results', [])
29
30 for result in organic:
31 if target_domain in result.get('link', ''):
32 results.append({
33 "keyword": keyword,
34 "position": result["rank"],
35 "page": result["link"]
36 })
37 found = True
38 break
39 else:
40 print(f"Request failed for '{keyword}' page {page}: {response.status_code}")
41 break
42
43 if not found:
44 results.append({
45 "keyword": keyword,
46 "position": "Not in top 100",
47 "page": "-"
48 })

The key difference from before is the nested loop, we now paginate through up to 10 pages to cover 100 results. But notice the found flag at the outer loop level: the moment your domain is found on any page, we break out of both loops immediately and stop spending API credits on that keyword.

This is important for cost efficiency. If your domain ranks #3 for a keyword, the script finds it on page 0 and moves on; it doesn’t burn 9 more API calls unnecessarily.

Finally, we can use pandas in order to store the data in a CSV file.

1import requests
2import pandas as pd
3from datetime import date
4
5results = []
6target_domain = "scrapingdog.com"
7
8keywords = ['web scraping api', 'web scraping tool', 'google web scraping', 'best serp api', 'google scraping api']
9api_key = "your-api-key"
10url = "https://api.scrapingdog.com/google/"
11
12for keyword in keywords:
13 found = False
14
15 for page in range(0, 10):
16 if found:
17 break
18
19 params = {
20 "api_key": api_key,
21 "query": keyword,
22 "country": "us",
23 "page": page
24 }
25 response = requests.get(url, params=params)
26
27 if response.status_code == 200:
28 data = response.json()
29 organic = data.get('organic_results', [])
30
31 for result in organic:
32 if target_domain in result.get('link', ''):
33 results.append({
34 "date": date.today(),
35 "keyword": keyword,
36 "position": result["rank"],
37 "page": result["link"]
38 })
39 found = True
40 break
41 else:
42 print(f"Request failed for '{keyword}' page {page}: {response.status_code}")
43 break
44
45 if not found:
46 results.append({
47 "date": date.today(),
48 "keyword": keyword,
49 "position": "Not in top 100",
50 "page": "-"
51 })
52
53df = pd.DataFrame(results)
54df.to_csv('rank.csv', index=False, encoding='utf-8')
55print(f"Done! Tracked {len(results)} keywords.")

We’ve added a date field to every row. When you run this script daily and append results over time, you'll have a full historical record of exactly when your rankings changed. Without dates, your CSV is just a snapshot. With dates, it becomes a trend you can act on.

Rank Tracking Result

Schedule Daily Runs with Email Alerts

Running the script manually every day defeats the purpose. Let’s automate it using the schedule library and send yourself an email summary each morning.

First, install the dependency:

1pip install schedule

Then update your script:

1import requests
2import pandas as pd
3import schedule
4import time
5import smtplib
6import os
7from email.mime.text import MIMEText
8from email.mime.multipart import MIMEMultipart
9from email.mime.base import MIMEBase
10from email import encoders
11from datetime import date
12
13target_domain = "scrapingdog.com"
14keywords = ['web scraping api', 'web scraping tool', 'google web scraping', 'best serp api', 'google scraping api']
15api_key = "your-api-key"
16url = "https://api.scrapingdog.com/google/"
17
18EMAIL_SENDER = "[email protected]"
19EMAIL_PASSWORD = "your-app-password" # Use an app password, not your main Gmail password
20EMAIL_RECEIVER = "[email protected]"
21
22
23def track_rankings():
24 results = []
25
26 for keyword in keywords:
27 found = False
28
29 for page in range(0, 10):
30 if found:
31 break
32
33 params = {
34 "api_key": api_key,
35 "query": keyword,
36 "country": "us",
37 "page": page
38 }
39 response = requests.get(url, params=params)
40
41 if response.status_code == 200:
42 data = response.json()
43 organic = data.get('organic_results', [])
44
45 for result in organic:
46 if target_domain in result.get('link', ''):
47 results.append({
48 "date": date.today(),
49 "keyword": keyword,
50 "position": result["rank"],
51 "page": result["link"]
52 })
53 found = True
54 break
55 else:
56 print(f"Request failed for '{keyword}' page {page}: {response.status_code}")
57 break
58
59 if not found:
60 results.append({
61 "date": date.today(),
62 "keyword": keyword,
63 "position": "Not in top 100",
64 "page": "-"
65 })
66
67 # Append mode for historical tracking
68 df = pd.DataFrame(results)
69 file_exists = os.path.isfile('rank.csv')
70 df.to_csv('rank.csv', mode='a', header=not file_exists, index=False, encoding='utf-8')
71
72 send_email(results)
73 print(f"[{date.today()}] Tracking complete.")
74
75
76def send_email(results):
77 body = f"Rank Tracking Report — {date.today()}\n\n"
78 for r in results:
79 body += f"{r['keyword']}: Position {r['position']}\n"
80
81 msg = MIMEMultipart()
82 msg['From'] = EMAIL_SENDER
83 msg['To'] = EMAIL_RECEIVER
84 msg['Subject'] = f"Daily Rank Report — {date.today()}"
85 msg.attach(MIMEText(body, 'plain'))
86
87 with open('rank.csv', 'rb') as f:
88 part = MIMEBase('application', 'octet-stream')
89 part.set_payload(f.read())
90 encoders.encode_base64(part)
91 part.add_header('Content-Disposition', 'attachment; filename="rank.csv"')
92 msg.attach(part)
93
94 with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server:
95 server.login(EMAIL_SENDER, EMAIL_PASSWORD)
96 server.sendmail(EMAIL_SENDER, EMAIL_RECEIVER, msg.as_string())
97
98 print("Email sent!")
99
100
101# Run every day at 8:00 AM
102schedule.every().day.at("08:00").do(track_rankings)
103
104print("Scheduler running... Press Ctrl+C to stop.")
105while True:
106 schedule.run_pending()
107 time.sleep(60)

The CSV uses append mode (mode='a') so every daily run adds new rows rather than overwriting yesterday's data. The email sends the full CSV as an attachment so you have everything in your inbox each morning.

Gmail Tip: Don’t use your regular Gmail password in the script.

Go to your Google Account → Security → App Passwords and generate a dedicated app password for this script.

This keeps your main account secure and prevents authentication issues while sending emails programmatically.

That’s the complete rank tracker. With pagination handling, early exit on match, and historical CSV logging, you now have a production-ready script that tracks your keyword positions daily, that too for a fraction of what Semrush or Ahrefs would charge.

Rank Tracking using No-Code Tools (n8n)

After the removal of the num=100 parameter, which basically allowed us to get 100 Google search results in one go, we decided to build one using n8n. 

If you happen to be a no-code tool enthusiast & rank tracking is something you are looking to do at an economical cost, this tutorial can help. 

If you would like to read along the text & understand the whole workflow, you can check out this blog. You will also find the blueprint for this automation there. 

Key Takeaways:

  • The tutorial explains how to build an automated keyword rank tracker in Python using a Google SERP API.

  • It shows how to send search queries, parse the response, and extract the ranking position of your target domain.

  • The script tracks organic search results and helps monitor keyword position changes over time.

  • You can schedule the script to run daily and store results to create historical ranking data.

  • This method eliminates manual rank checking and provides a scalable way to monitor SEO performance.

Conclusion

Keyword rank tracking is a crucial part of any search engine optimization (SEO) strategy, enabling businesses to monitor their performance and refine their approaches to stay ahead of the competition.

Using Python and the Google Search API, you can automate the process and efficiently gather accurate ranking data.

This not only saves time but also provides insights that empower data-driven decisions for improving visibility and driving organic traffic.

You can monitor your rankings or analyze competitors, this combination provides a scalable and cost-effective solution.

Frequently Asked Questions (FAQs)

1. Can I track competitor domains too?

Yes. You can replace target_domain with any competitor’s domain and track their rankings for the same keywords. The script doesn’t care whose domain it checks, it simply scans the SERP results and reports the position if found.

Google search results contain publicly accessible data. However, you should always follow platform terms and use scraping responsibly. Using an API reduces technical risks like aggressive scraping or server overload.

3. Can I track rankings for any country?

Yes. The country parameter lets you track rankings in specific markets such as "us", "gb", "in", "au", etc. This makes it easy to monitor performance across different geographic regions.

4. How many API credits does this script use per day?

It depends on how many keywords you track and how deep you paginate. In the worst case (10 pages per keyword), it uses up to 10 API calls per keyword per day. But if your domain ranks on page 1, it stops early and uses fewer credits.

5. Is rank tracking with an API accurate?

Yes. The script pulls live organic Google results directly from the API, so the ranking positions reflect real-time search data. The accuracy depends on the selected country and query parameters, just like any professional SEO tool.

Additional Sources

Try Scrapingdog for Free!

Get 200 free credits to spin the API. No credit card required!