To use the SellerMagnet API as an Amazon South Africa product API, call it with marketplaceId=AE08WJ6YKNBMC: the request goes to amazon.co.za and prices come back in ZAR. Product lookup, offers, search, deals, bestsellers and seller feedback all answer for amazon.co.za; price history, sales estimates and the ASIN converter return a free 400. Amazon's own offer carries its South African seller ID, and the default delivery postcode is the four-character string 0083.
Key Takeaways
- amazon.co.za is marketplace AE08WJ6YKNBMC and is priced in ZAR (symbol R, not Brazil's R$).
- Six endpoints answer on amazon.co.za; statistics, estimated sales and the converter return a free 400 and no data.
- Amazon's own offer is
sellerId"Amazon" withamazonSellerIdA34KVLZUJN6MA on amazon.co.za. - Product lookup always asks amazon.co.za for postcode 0083; keep postcodes and ASINs as text so no leading zero is lost.
- Bestsellers need a
category_idfrom amazon.co.za's own tree (14 top-level categories); an ID from another store's tree gets a free 400.
What is different about the Amazon South Africa product API?
The request format is the same as for every other store: GET, query parameters, the key in the X-Api-Key header. What changes are a few values, the endpoint coverage and the postcode. Prices come back as plain decimal numbers in ZAR, the price the page shows; there is no separate VAT field. The currency symbol is a bare R, while Brazil's is R$, so compare currency_code rather than the symbol when one script handles several stores.
| Item | amazon.co.za |
|---|---|
| Marketplace ID | AE08WJ6YKNBMC |
| Store | amazon.co.za |
| Currency | ZAR (South African Rand), symbol R |
| Default postcode | "0083", a string with a leading zero |
| Page language | English |
| Amazon's own offer | sellerId "Amazon", amazonSellerId A34KVLZUJN6MA |
| Bestseller category tree | amazon.co.za's own: 14 top-level categories |
| History endpoints | free 400, no data |
The amazon.co.za entry of /amazon-get-marketplaces as sent (keyed by marketplace ID)
{
"AE08WJ6YKNBMC": {
"currency_code": "ZAR",
"currency_name": "South African Rand",
"currency_symbol": "R",
"geo_location": "0083",
"marketplace_domain": "amazon.co.za",
"marketplace_name": "Amazon ZA"
}
}
Amazon's own APIs answer different questions. The Selling Partner API, which serves amazon.co.za through its Europe endpoint, is for sellers and the apps they authorise, and the Creators API, which replaces the deprecated Product Advertising API 5, is for affiliates: Amazon requires at least 10 qualifying sales within the past 30 days for access. To read any amazon.co.za listing, its offers and its bestsellers without a seller or affiliate account, the endpoints below need only an API key.
Recognising Amazon's own offer on amazon.co.za
An offer from Amazon itself comes back with sellerId "Amazon". On amazon.co.za it also carries Amazon's first-party seller ID for the store in amazonSellerId: A34KVLZUJN6MA. Third-party offers have amazonSellerId null. Product lookup reports the same pair in productInfo.buyBoxInfo, so one lookup call tells you whether Amazon holds the featured offer. Not every store has such an ID (amazon.sg and amazon.in do not), so code that runs across stores should test sellerId == "Amazon" first. The is Amazon selling on this listing guide covers the same check across stores.

Which postcode does the API use for amazon.co.za?
The default for amazon.co.za is 0083, as the marketplace list above shows. Product lookup always asks for it: a geo_location added to a lookup call is not applied. Setting the postcode is best effort: if amazon.co.za refuses it, the reading comes from the location Amazon gave the session, and the response does not say which. The offers endpoint does take geo_location and falls back to 0083 when you send none. Amazon's own help pages say shoppers may see a different featured offer from a different shipping location, so treat a price as one reading for that postcode. Keep postcodes as text: a spreadsheet column formatted as a number turns 0083 into 83. The search geo_location guide covers how a postcode works on search.
Endpoint coverage on amazon.co.za
Six of the ten endpoints only check that the marketplace ID is valid, so they answer on all 23 marketplaces, amazon.co.za included. The three history endpoints cover only 11 marketplaces and turn every other one away before the credit is taken: amazon.co.za gets a 400 with the message "This endpoint is not available for the requested marketplace" followed by the list of supported stores. That call costs nothing, but it returns no data either. The endpoint coverage overview shows every store at once.

How do I check amazon.co.za products in Python?
The script below reads a list of ASINs from asins.csv, looks each one up once on amazon.co.za and prints the featured offer's price in ZAR, its holder, the bestseller rank and the listing date. Before any call it drops duplicates, Excel's 4.00638E+12 style values and numbers that lost a leading zero, because product lookup bills a malformed ASIN like any other request. It stops the run on a 401/403 and after three calls that keep failing. It uses sellermagnet.py (ApiError, new_session) and retry.py (get_with_retry) from the Python quickstart.
asins.csv (illustrative input)
asin
B0ZAKETTL1
B0ZAPHONE2
b0zakettl1
4.00638E+12
306406152
B0ZAGONE04
B0ZACHAIR5
B0ZACABLE6
za_catalogue_check.py - price, featured offer, rank and listing date on amazon.co.za
"""Amazon South Africa (amazon.co.za) catalogue check: ZAR price, featured offer, rank and listing date per ASIN.
amazon.co.za is marketplace AE08WJ6YKNBMC, priced in ZAR. One product lookup (1 credit) per ASIN. What the
script relies on:
1. Amazon's own offer comes back as sellerId "Amazon" with amazonSellerId A34KVLZUJN6MA on amazon.co.za.
2. Product lookup asks amazon.co.za for the store's default postcode "0083" (best effort). Keep postcodes
and ASINs as text: a spreadsheet that stores them as numbers drops the leading zero ("0083" becomes 83).
3. amazon.co.za pages are in English, so listedSinceDate can be filled from the "Date First Available" row.
4. amazon.co.za is not one of the 11 marketplaces with price history: statistics, estimated sales and the ASIN
converter answer it with a free 400. The script never sends those calls.
Input: asins.csv with one column named "asin". Helpers: sellermagnet.py and retry.py from
https://sellermagnet-api.com/blog/amazon-product-api-python
"""
import csv
import re
import sys
import requests
from retry import get_with_retry
from sellermagnet import ApiError, new_session
MARKET = "AE08WJ6YKNBMC" # amazon.co.za, prices in ZAR
CURRENCY = "ZAR" # the symbol is "R" (Brazil's is "R$"): compare the code, not the symbol
AMAZON_ZA = "A34KVLZUJN6MA" # Amazon's first-party seller ID on amazon.co.za
HISTORY_MARKETS = {"ATVPDKIKX0DER", "A2EUQ1WTGCTBG2", "A1AM78C64UM0Y8", "A2Q3Y263D00KWC", "A1F83G8C2ARO7P",
"A1PA6795UKMFR9", "A13V1IB3VIYZZH", "APJ6JRA9NG5V4", "A1RKKUPIHCS9HS", "A21TJRUUN4KGV",
"A1VC38T7YXB528"} # the 11 marketplaces with statistics, estimated sales, converter
MAX_FAILED = 3 # 502/503 are billed on every attempt: stop after 3 calls that keep failing
class Stop(Exception):
"""401/403: the key or the credits are the problem, so every further call would fail the same way."""
def call(session, endpoint, **params):
try:
return get_with_retry(session, endpoint, **params)
except ApiError as err:
if err.status in (401, 403):
raise Stop(str(err)) from err
raise
def read_asins(path):
"""Unique ASINs in file order plus the rejected rows, all checked before any call is paid for.
Lookup does not check the ASIN format, so a malformed value would still cost a credit."""
with open(path, newline="", encoding="utf-8-sig") as fh: # utf-8-sig: Excel's CSV starts with a BOM
reader = csv.DictReader(fh)
header = [h.strip().lower() for h in reader.fieldnames or []]
if "asin" not in header:
raise SystemExit(f"{path}: no 'asin' column (header {reader.fieldnames}), nothing sent")
col = reader.fieldnames[header.index("asin")]
asins, rejected, seen = [], [], set()
for line, rec in enumerate(reader, start=2):
value = (rec.get(col) or "").strip().upper()
if not value:
continue
if re.fullmatch(r"[A-Z0-9]{10}", value):
if value in seen:
rejected.append((line, value, "duplicate, looked up once"))
else:
seen.add(value)
asins.append(value)
elif re.fullmatch(r"\d{1,9}", value):
rejected.append((line, value, "too short: a spreadsheet may have dropped a leading zero"))
else:
rejected.append((line, value, "not an ASIN"))
return asins, rejected
def featured(info):
"""(price, holder) from productInfo; price None when nothing is featured or the currency is not ZAR."""
box = info.get("buyBoxInfo") or {}
price, seller = box.get("price"), box.get("sellerId")
if box.get("currencyCode") not in (None, CURRENCY):
return None, f"price in {box.get('currencyCode')}, not {CURRENCY}: not used"
if not isinstance(price, (int, float)) or price <= 0: # "N/A" = no featured offer
return None, "no featured offer"
if seller == "Amazon":
first_party = box.get("amazonSellerId")
holder = "Amazon" if first_party == AMAZON_ZA else f"Amazon (amazonSellerId {first_party})"
elif seller and seller != "N/A":
holder = f"seller {seller}"
else:
holder = "seller not read"
return round(price, 2), holder
def rank_of(info):
main = (info.get("bestsellerRanks") or {}).get("main_category") or {}
return f"{main['rank']:,}" if isinstance(main.get("rank"), int) and main["rank"] > 0 else "-"
def row(asin, price="-", rank="-", listed="-", note=""):
print(f"{asin:<11} {price:>9} {rank:>7} {listed:<10} {note}")
def main(path="asins.csv"):
asins, rejected = read_asins(path)
for line, value, why in rejected:
print(f"skipped line {line}: {value!r} {why}")
history = "yes" if MARKET in HISTORY_MARKETS else "not available (free 400), not called"
print(f"amazon.co.za: {len(asins)} ASINs to look up (1 credit each + billed retries); price history: {history}")
print()
row("asin", "ZAR", "rank", "listed", "featured offer")
session = new_session()
failed = read = amazon_holds = not_found = 0
for asin in asins:
if failed >= MAX_FAILED:
print(f"stopped after {MAX_FAILED} failed calls")
break
try:
info = call(session, "amazon-product-lookup", asin=asin, marketplaceId=MARKET)["productInfo"]
except Stop as err:
print(f"stopped: {err}")
break
except ApiError as err:
if err.status == 404:
not_found += 1
row(asin, note="not found on amazon.co.za (billed 404)")
else:
row(asin, note=f"error {err}")
failed += err.status >= 500
continue
except (requests.ConnectionError, requests.Timeout) as err:
row(asin, note=f"error {type(err).__name__}")
failed += 1
continue
read += 1
price, holder = featured(info)
amazon_holds += holder.startswith("Amazon")
listed = info.get("listedSinceDate") or "-" # null: the page had no date row
row(asin, f"{price:,.2f}" if price is not None else "-", rank_of(info), listed, holder)
print(f"\nread {read} of {len(asins)}, {not_found} not found; Amazon holds the featured offer on {amazon_holds}")
if __name__ == "__main__":
main(*sys.argv[1:2])
Output (illustrative data: a retried 502, a 404, a listing without a featured offer)
skipped line 4: 'B0ZAKETTL1' duplicate, looked up once
skipped line 5: '4.00638E+12' not an ASIN
skipped line 6: '306406152' too short: a spreadsheet may have dropped a leading zero
amazon.co.za: 5 ASINs to look up (1 credit each + billed retries); price history: not available (free 400), not called
asin ZAR rank listed featured offer
B0ZAKETTL1 899.00 152 2023-03-14 Amazon
B0ZAPHONE2 4,299.00 37 2024-09-02 seller A1ZASELLER02
B0ZAGONE04 - - - not found on amazon.co.za (billed 404)
B0ZACHAIR5 - - - no featured offer
B0ZACABLE6 149.99 2,113 - Amazon
read 4 of 5, 1 not found; Amazon holds the featured offer on 2
- Amazon in the last column means
buyBoxInfo.sellerIdwas "Amazon" andamazonSellerIdwas A34KVLZUJN6MA, as on every amazon.co.za offer from Amazon itself. - seller A1ZASELLER02 is a third-party seller holding the featured offer; feed its ID to the seller feedback endpoint if you want its rating on amazon.co.za.
- no featured offer means the price came back as "N/A": no featured offer, or no readable price, on that page right now. It is not an error and not proof of a stock-out; check again before acting.
- listed is
listedSinceDate, the page's "Date First Available". A dash means the page had no such row, not that the listing is new. - not found (billed 404) costs a credit like a successful call; the script counts it separately so it is never read as "no offer".
amazon.co.za has its own bestseller category tree
amazon.ie borrows the UK category tree because it has none of its own; amazon.co.za is not in that alias list and has its own tree with 14 top-level categories and 12,521 nodes. The names are in English, the top level uses slugs such as electronics or home, and deeper IDs are numeric (Electronics & Photo > Cell Phones & Communication is 28034760031). Those numeric IDs are specific to amazon.co.za: none of them appears in the amazon.com, amazon.co.uk or amazon.com.au tree. Take category_id from the category explorer, or pass the category name as amazon.co.za shows it; an ID from another marketplace's tree fails with "Invalid CategoryId", a free 400 answered before the credit is taken.
Does listedSinceDate work on amazon.co.za?
It can. amazon.co.za pages are in English, and the label list the API uses to find a product's "Date First Available" row includes the English phrase, which is the label amazon.co.za product pages show (for example a "Date First Available" row reading 9 May 2024). So productInfo.listedSinceDate is filled when the page has that row. A null still happens on pages without it, as for the last product in the example. Titles and category names come back in English.
Credit cost of an amazon.co.za check
1 credit per request, as on every store. The script costs 1 credit per unique ASIN, plus each billed retry: a 502 or 503 is charged on every attempt, a 500 without Retry-After is refunded. A 404 for an ASIN is billed. An invalid marketplace ID, an unknown category ID and the history endpoints' amazon.co.za 400 are free. The example run made 6 calls: 5 for the five unique ASINs and 1 retried 502; the three skipped rows cost nothing.
Frequently Asked Questions
What is the Amazon South Africa marketplace ID?
AE08WJ6YKNBMC. Pass it as marketplaceId and the request goes to amazon.co.za, with prices in ZAR. A country code like "ZA" or a domain like "amazon.co.za" is rejected with a free 400 Invalid marketplaceId.
How do I know if Amazon itself sells a product on amazon.co.za?
The featured offer or an offer in the list has sellerId "Amazon". On amazon.co.za that offer also carries amazonSellerId A34KVLZUJN6MA, Amazon's own seller ID for the store; third-party offers have null there.
Can I get Amazon South Africa price history?
Not from this API. Statistics, estimated sales and the ASIN converter cover 11 marketplaces and answer amazon.co.za with a free 400 and no data. Store your own lookup or offers readings if you need a history.
Which postcode does the API use for amazon.co.za?
0083 by default. Product lookup always asks for it; the offers endpoint takes another postcode in geo_location. Send it as text, because a postcode stored as a number loses its leading zero.
Which category IDs work for amazon.co.za bestsellers?
IDs from amazon.co.za's own tree: 14 top-level slugs such as electronics and numeric IDs below them, for example 28034760031. An ID from another store's tree gets a free 400 Invalid CategoryId.
Bottom line: use AE08WJ6YKNBMC for amazon.co.za, expect ZAR, recognise Amazon by sellerId (with A34KVLZUJN6MA as its ID), keep 0083 and your ASINs as text, and keep history calls for the 11 covered stores. A free account includes 150 credits.