Playbook · SEO & SERP Research

Check where a site ranks on Google by city and device

Search Google as a user in a specific city on desktop or mobile and get the organic results with their positions, then find where your site ranks.

In short

Call /search with the keyword, gl, a city-level location and the device. Find your domain in organic_results to get its position, and repeat for each city and device you track.

The use case

Rankings depend on where the searcher is and what device they use. A site can be first in one city and lower in another, or drop on mobile. Checking from the right location is the only way to see what your customers see.

Who does this: SEO agencies and rank-tracking tools, local businesses tracking their own keywords, and marketers checking campaigns in several markets.

How to do it

Uses the Real-Time Web Search API, tested live on October 28, 2026. Call /search with the keyword, a location and a device. Here, "best running shoes" on mobile in Austin:

import requests

r = requests.get(
    "https://api.openwebninja.com/realtime-web-search/v2/search",
    headers={"x-api-key": "YOUR_API_KEY"},
    params={"q": "best running shoes", "gl": "us", "location": "Austin, Texas, United States",
            "device": "mobile", "num": 10},
)
for o in r.json()["data"]["organic_results"]:
    print(o["position"], o["domain"])
Result (Python)
1 runrepeat.com
2 www.runnersworld.com
3 www.reddit.com
4 sixminutemile.com
5 www.nike.com
6 www.fleetfeet.com
7 www.amazon.com
8 believeintherun.com
Full response of the cURL call above · JSON
{
  "status": "OK",
  "request_id": "03c58d3d-3e74-4696-af12-86af1287c1d5",
  "parameters": {
    "q": "best running shoes",
    "location": "Austin, Texas, United States",
    "nfpr": "0",
    "nhr": "0",
    "start": 0,
    "num": 10,
    "gl": "us",
    "hl": "en",
    "device": "mobile",
    "fetch_ai_overviews": false,
    "return_organic_result_video_thumbnail": false,
    "deduplicate": false
  },
  "data": {
    "total_organic_results": 0,
    "organic_results": [
      {
        "title": "7 Best Running Shoes in 2026",
        "url": "https://runrepeat.com/guides/best-running-shoes",
        "snippet": "The New Balance 1080 v15 stands out in the all-rounder game, bringing a whole new level of comfort while sustaining lightness and responsiveness ...",
        "source": "RunRepeat",
        "displayed_link": "https://runrepeat.com",
        "date": "Sep 12, 2026",
        "domain": "runrepeat.com",
        "snippet_highlighted_words": [
          "The New Balance 1080 v15"
        ],
        "position": 1,
        "rank": 1
      },
      {
        "title": "What are the best running shoes that you'd actually buy again?",
        "url": "https://www.reddit.com/r/runninglifestyle/comments/1u5x7mx/what_are_the_best_running_shoes_that_youd/",
        "snippet": "I’m finally replacing my running shoes and I forgot how overwhelming this category is. Every list says something different and everyone seems to ...",
        "source": "Reddit · r/runninglifestyle",
        "displayed_link": "230+ comments · 4 months ago",
        "domain": "www.reddit.com",
        "position": 2,
        "rank": 2
      },
      {
        "title": "The 15 Best Running Shoes of 2026",
        "url": "https://www.runnersworld.com/gear/a19663621/best-running-shoes/",
        "snippet": "6 days ago — For new runners we recommend a shoe like the Brooks Ghost or Nike Pegasus as a starting point. These shoes are moderately cushioned and offer ...",
        "source": "Runner's World",
        "displayed_link": "https://www.runnersworld.com",
        "domain": "www.runnersworld.com",
        "snippet_highlighted_words": [
          "Brooks Ghost or Nike Pegasus"
        ],
        "position": 3,
        "rank": 3
      },
      {
        "title": "Best Running Shoes of the Year: 6 Top-Shelf Models",
        "url": "https://sixminutemile.com/post/six-of-the-best-running-shoes-of-the-year/",
        "snippet": "Six of the Very Best Running Shoes of the Year · ASICS Megablast · Adidas Adizero Evo SL · FAST-R Nitro Elite 3 · Mount to Coast H1 · Norda 005.",
        "source": "Six Minute Mile",
        "displayed_link": "https://sixminutemile.com",
        "date": "Dec 12, 2025",
        "domain": "sixminutemile.com",
        "price": "$120 to $325",
        "position": 4,
        "rank": 4
      },
      {
        "title": "Best Men's Road Running Shoes",
        "url": "https://www.amazon.com/Best-Sellers-Men's-Road-Running-Shoes/zgbs/fashion/14210389011",
        "snippet": "Road Running · #1 · Brooks Men's Adrenaline GTS 25 Running Shoe · #2 · Under Armour Men's Charged Assert 10 Shoes · #3 · Brooks Men's Revel 8 Running Shoe · #4.",
        "source": "Amazon.com",
        "displayed_link": "https://www.amazon.com",
        "domain": "www.amazon.com",
        "rating": 4.5,
        "delivery": "Free delivery",
        "position": 5,
        "rank": 5
      },
      {
        "title": "Top Rated Running Shoes | REI Co-op",
        "url": "https://www.rei.com/s/top-rated-running-shoes",
        "snippet": "Shop for Top Rated Running Shoes at REI - Browse our extensive selection of trusted outdoor brands and high-quality recreation gear.",
        "source": "REI",
        "displayed_link": "https://www.rei.com",
        "domain": "www.rei.com",
        "snippet_highlighted_words": [
          "Shop for Top Rated Running Shoes at REI"
        ],
        "price": "$90 to $295",
        "rating": 4.8,
        "delivery": "Free delivery over $100",
        "position": 6,
        "rank": 6
      },
      {
        "title": "In your opinion what is the best running shoes?",
        "url": "https://www.letsrun.com/forum/flat_read.php?thread=8528045&page=1",
        "snippet": "In my post, I review shoes like the Nike Pegasus 37 and Nike Structure 22, The Asics GT 2000 8, The ASICS Gel Nimbus, The Brooks Glycerin 18, ...",
        "source": "LetsRun.com",
        "displayed_link": "https://www.letsrun.com",
        "date": "Nov 8, 2017",
        "domain": "www.letsrun.com",
        "snippet_highlighted_words": [
          "Nike Pegasus 37"
        ],
        "position": 7,
        "rank": 7
      },
      {
        "title": "Running Shoes Guru: Running Shoes Reviews and Buying Guide",
        "url": "https://www.runningshoesguru.com/",
        "snippet": "Guides to running shoe brands: their models, collection and technology explained. · Best Asics · Best Nike · Best Brooks · Best Saucony · Best New Balance · Best ...",
        "source": "Running Shoes Guru",
        "displayed_link": "https://www.runningshoesguru.com",
        "domain": "www.runningshoesguru.com",
        "position": 8,
        "rank": 8
      },
      {
        "title": "The Best Beginner Running Shoes 2026",
        "url": "https://theruntesters.com/the-best-running-shoes-for-beginners/",
        "snippet": "The Puma Velocity Nitro 4 is one of our favourite shoes for runners of all levels, and one of the best value shoes on the market as well. It's light, ...",
        "source": "The Run Testers",
        "displayed_link": "https://theruntesters.com",
        "domain": "theruntesters.com",
        "snippet_highlighted_words": [
          "Puma Velocity Nitro 4"
        ],
        "position": 9,
        "rank": 9
      }
    ],
    "has_ai_overviews": true
  }
}

For a whole list

Check one domain for a keyword across cities and devices:

import csv
import requests

API_KEY = "YOUR_API_KEY"
URL = "https://api.openwebninja.com/realtime-web-search/v2/search"
DOMAIN = "runnersworld.com"
keyword = "best running shoes"
locations = ["New York, New York, United States", "Austin, Texas, United States"]

with open("rankings.csv", "w", newline="") as f:
    w = csv.writer(f)
    w.writerow(["keyword", "location", "device", "position", "url"])
    for location in locations:
        for device in ["desktop", "mobile"]:
            results = (requests.get(URL, headers={"x-api-key": API_KEY}, params={
                "q": keyword, "gl": "us", "location": location, "device": device, "num": 10,
            }, timeout=60).json().get("data") or {}).get("organic_results") or []
            hit = next((o for o in results if DOMAIN in o["domain"]), None)
            w.writerow([keyword, location, device, hit["position"] if hit else "not in top 10",
                        hit["url"] if hit else ""])
rankings.csv
keyword,location,device,position,url
best running shoes,"New York, New York, United States",desktop,1,https://www.runnersworld.com/gear/a69801110/amanda-furrer-best-running-shoes-i-tested-in-2025/
best running shoes,"New York, New York, United States",mobile,1,https://www.runnersworld.com/gear/a69801110/amanda-furrer-best-running-shoes-i-tested-in-2025/
best running shoes,"Austin, Texas, United States",desktop,1,https://www.runnersworld.com/gear/a69801110/amanda-furrer-best-running-shoes-i-tested-in-2025/
best running shoes,"Austin, Texas, United States",mobile,3,https://www.runnersworld.com/gear/a19663621/best-running-shoes/

Four checks took 19 seconds.

Good to know

  • Location and device change the result. runnersworld.com was first in New York and on desktop in Austin, but third on mobile in Austin, with a different page.
  • Rankings move between calls. Positions 2 and 3 swapped between two identical calls a few seconds apart, so track averages, not single checks.
  • num=10 can return fewer organic results when Google shows other blocks; this query returned 8.
  • Use a city-level location from the supported list, plus gl for the country.

Frequently asked questions

How do I check my Google ranking as if I were searching from a specific city?

City-level locations from the published list at openwebninja.s3.us-east-1.amazonaws.com/locations.json, for example "Austin, Texas, United States".

How do I check whether my site ranks differently on mobile than on desktop?

Yes. Set device=mobile (or tablet). The default is desktop.

Can I see whether Google shows an AI Overview for my keyword in the same call?

Yes. Add fetch_ai_overviews=true; when an AI Overview is shown, the request costs two credits instead of one.

Start building with real-time web data

Every API includes a free tier. No credit card required, and the first request is a minute away.