To track an ASIN's keyword rank on Amazon, call the SellerMagnet /api/amazon-search endpoint with the keyword, the marketplace and count=50, then find your ASIN in searchResults. Each result carries a position and a sponsored flag, so one request gives you both the page position and the organic rank. Store one row per keyword per day and you have a rank history that costs one credit per keyword per marketplace per check.
Key Takeaways
- Search returns the first results page only, in page order, up to 50 products per request.
- position counts sponsored and organic products together; count the non-sponsored ones yourself for the organic rank.
- An ASIN missing from the results is not among the priced page-one products returned - store NULL, not 51.
- geo_location takes a ZIP or postcode to request what shoppers in one region see; it is best-effort.
- Cost is one credit per keyword per marketplace per check; count above 50 is a billed 400.
What does the search API return for a keyword?
The endpoint reads the first page of Amazon's search results for the keyword and returns up to count products (default 30, maximum 50) in the order the page shows them. position is 1-based and consecutive across the products returned, and sponsored placements are numbered like everything else, each with sponsored: true. Products shown without a price are skipped and do not consume a number.
Two results from /api/amazon-search (trimmed)
{
"success": true,
"data": {
"searchResults": [
{
"position": 1,
"asin": "B0CL5KNB9M",
"sponsored": false,
"productTitle": "PlayStation®5 Digital Edition (slim)",
"listingPrice": {"price": {"total": "449.00", "currency_code": "USD"}},
"reviewAmount": 7209,
"reviewRating": 4.7
},
{
"position": 2,
"asin": "B0DGY63Z2H",
"sponsored": false,
"productTitle": "PlayStation 5 Pro Console",
"listingPrice": {"price": {"total": "699.00", "currency_code": "USD"}},
"reviewAmount": 1373,
"reviewRating": 4.4
}
]
}
}
| Field | Type | What it tells you |
|---|---|---|
position | integer, 1-based | Place on page one, sponsored results included |
sponsored | boolean | true for a paid placement |
asin | string | The product in that slot - match your ASIN here |
listingPrice.price.total | string | Displayed price, e.g. "449.00" - convert before maths |
reviewAmount / reviewRating | number | Social proof of the listings around you |
How do I get the organic rank from a search result?
Your organic rank is your position among the non-sponsored results only. Walk the results in order, count the organic ones, and stop at your ASIN. Keep the page position as well: an organic rank of 3 sitting at page position 7, behind four ads, is a different shelf from organic 3 at position 3. An ASIN can also appear twice - once as an ad and once organically - so record both.

How do I build a daily keyword rank tracker in Python?
The script below reads a list of keyword, ASIN and marketplace triples, runs one search per keyword, and writes the organic rank, page position and sponsored position to SQLite. It stores NULL when the ASIN is not among the results, so averages are not skewed by an invented rank.
rank_tracker.py - one search per keyword, one row per day
import datetime as dt
import os
import sqlite3
import requests
API = "https://sellermagnet-api.com/api/amazon-search"
TRACKED = [ # (keyword, asin, marketplaceId)
("ps5 console", "B0CL5KNB9M", "ATVPDKIKX0DER"),
("playstation 5 slim", "B0CL5KNB9M", "ATVPDKIKX0DER"),
]
db = sqlite3.connect("ranks.db")
db.execute("""CREATE TABLE IF NOT EXISTS ranks (
day TEXT, keyword TEXT, marketplace TEXT, asin TEXT,
organic_rank INTEGER, page_position INTEGER, sponsored_position INTEGER,
results INTEGER, PRIMARY KEY (day, keyword, marketplace, asin))""")
def ranks_for(results: list, asin: str) -> dict:
out = {"organic_rank": None, "page_position": None, "sponsored_position": None}
organic = 0
for item in results: # already in page order
if not item.get("sponsored"):
organic += 1
if item.get("asin") != asin:
continue
if item.get("sponsored"):
out["sponsored_position"] = out["sponsored_position"] or item["position"]
elif out["organic_rank"] is None:
out["organic_rank"], out["page_position"] = organic, item["position"]
return out
today = dt.date.today().isoformat()
for keyword, asin, marketplace in TRACKED:
resp = requests.get(API, params={"q": keyword, "marketplaceId": marketplace, "count": 50,
"api_key": os.environ["SELLERMAGNET_API_KEY"]}, timeout=90)
try:
body = resp.json()
except ValueError: # e.g. an HTML error page from a proxy
body = {}
if resp.status_code != 200 or not body.get("success"):
print(f"skip {keyword!r}: {resp.status_code} {body.get('message')}")
continue
results = body["data"]["searchResults"]
row = ranks_for(results, asin)
db.execute("INSERT OR REPLACE INTO ranks VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
(today, keyword, marketplace, asin, row["organic_rank"], row["page_position"],
row["sponsored_position"], len(results)))
db.commit()
print(keyword, row)
Why the results column
Storing how many results came back tells you whether a missing ASIN means "not in the top 50" or "the page was short that day". With count=50, compare ranks only between days where results is 50.
Once the table has a few weeks of rows, one query answers the question you actually care about: which keywords moved since last week.
Organic rank today versus seven days ago
SELECT t.keyword,
w.organic_rank AS week_ago,
t.organic_rank AS today,
w.organic_rank - t.organic_rank AS gained
FROM ranks t
LEFT JOIN ranks w
ON w.keyword = t.keyword AND w.asin = t.asin AND w.marketplace = t.marketplace
AND w.day = date(t.day, '-7 days')
WHERE t.day = (SELECT MAX(day) FROM ranks)
-- NULL = entered or left the results: list those first, then the biggest movers
ORDER BY (w.organic_rank IS NULL OR t.organic_rank IS NULL) DESC, gained DESC;

How often should I check keyword rankings?
Page one is where the clicks are, which is why the tracker stops there: a product on page three is better described as "not ranking" than by its exact position. Once a day is enough for most sellers: organic rank moves with sales velocity and reviews, which change over days, not minutes. Run the tracker at a fixed hour so days compare fairly. Each check costs one credit per keyword per marketplace, so 100 keywords in two marketplaces tracked daily cost 200 credits a day. Check hourly only for a launch or a price test, and only for the handful of keywords involved.
crontab: run the tracker every day at 06:00
# m h dom mon dow command
0 6 * * * cd /opt/rank-tracker && SELLERMAGNET_API_KEY=... .venv/bin/python rank_tracker.py >> ranks.log 2>&1
Localised results with geo_location
Search results depend on the delivery address. Pass geo_location with a ZIP or postcode to request the page a shopper in that area sees; without it, the marketplace's default location is used. It is best-effort: if the location cannot be set, the search runs with the default location and the response does not say so. Check that two locations really return different results before you track them as separate series.
Keep count at 50 or below
A count above 50 returns HTTP 400 Count Max: 50 after the credit is charged. For every other status code and whether it is billed, see the error-handling guide.
Rank is half the story; the other half is why it moved. Pair each keyword with the ASIN's recorded sales rank and price from product statistics to see whether a jump followed a price cut, and use the bestsellers endpoint to watch the category around you. The search endpoint page lets you try a keyword in the browser first.
Frequently Asked Questions
How do I check my ASIN's keyword rank on Amazon?
Search the keyword with /api/amazon-search and count=50, then find your ASIN in searchResults. Its position is the page position; count the non-sponsored results before it for the organic rank.
Does the search API include sponsored products?
Yes. Sponsored products are included and numbered in page order, each marked sponsored: true, so you can separate paid from organic placements.
Can I track rankings beyond page one?
No. The search endpoint returns the first results page only, up to 50 products. A missing ASIN is not among the returned products; listings without a displayed price are skipped.
How much does keyword rank tracking cost?
One credit per keyword per marketplace per check. Tracking 100 keywords in one marketplace once a day costs 100 credits a day.
Can I track rankings for a specific city or ZIP code?
You can request it: pass geo_location with a ZIP or postcode. It is best-effort; if the location cannot be set, the marketplace default is used without notice.
Bottom line: one search per keyword a day, organic rank counted without the ads, NULL when you are off page one, and a SQL query to spot the movers. A free account includes 500 credits - enough to track 10 keywords for seven weeks.