To decide which Amazon marketplace to sell a product on next, check the same ASIN on each candidate store: is it listed, how many sellers offer it New, does Amazon itself sell it, what does the featured offer cost, and how many units does it sell a month. /api/amazon-product-offers answers the first four per store, /api/amazon-product-search-estimated-sells the fifth on the stores with recorded history. Ten European stores cost about 15 credits per product; the script below builds the table and a first verdict.
Key Takeaways
- One offers call per store shows whether the ASIN is listed, how many New sellers compete and whether Amazon sells it.
- A 404 on a store means the ASIN is not listed there: you would create the listing rather than join one.
- Sales estimates exist on UK, DE, FR, IT and ES among the European stores; NL, BE, SE, PL and IE show competition only.
- Amazon itself on the listing, or eight or more New sellers, makes a store crowded for a newcomer.
- Prices come back in each store's currency (GBP, EUR, SEK, PLN) and include local VAT - compare net of VAT.
What decides whether a marketplace is worth entering?
Demand and competition. Demand is how much the product sells there; competition is how many sellers offer it New and whether Amazon is one of them, because a newcomer then competes with Amazon's own offer for the featured offer. A store where the product sells well and only two sellers compete is a better first step than the largest store with nine. Price differences between stores matter too, but part of the gap is VAT, which differs by country - the marketplace price comparison guide shows how to compare them net.
| Verdict | When | Means |
|---|---|---|
| Not listed | 404 on that store | You would create the listing |
| No New offer | Listed, no New offer on page 1 | Re-check once, then ask why |
| Room for another seller | 1-3 New sellers, no Amazon | The easiest entry |
| Competitive | 4-7 New sellers, no Amazon | Enter with a price plan |
| Crowded | Amazon sells it, or 8+ sellers | Think twice |
| Unknown | Error or timeout | Run that store again |
How do I compare one product across European Amazon stores?
store() makes one offers call per store - and one estimate where estimates exist - and returns a row. A 404 marks the ASIN as not listed; any other failure, after get_with_retry() has retried a 429 or 5xx, leaves the row as unknown, so it is checked again rather than misread. verdict() applies the thresholds from the table. get_with_retry(), new_session() and ApiError come from the Python quickstart; all marketplace IDs are in the marketplace IDs list.
expansion.py - competition and demand per European store
"""Where to launch next: competition for one ASIN on each European Amazon store."""
import threading
from concurrent.futures import ThreadPoolExecutor
import requests
from sellermagnet import ApiError, get_with_retry, new_session
STORES = {"A1F83G8C2ARO7P": "amazon.co.uk", "A1PA6795UKMFR9": "amazon.de", "A13V1IB3VIYZZH": "amazon.fr",
"APJ6JRA9NG5V4": "amazon.it", "A1RKKUPIHCS9HS": "amazon.es", "A1805IZSGTT6HS": "amazon.nl",
"AMEN7PMS3EDWL": "amazon.com.be", "A2NODRKZP88ZB9": "amazon.se", "A1C3SOZRARQ6R3": "amazon.pl",
"A28R8C7NBKEWEA": "amazon.ie"}
WITH_ESTIMATES = {"A1F83G8C2ARO7P", "A1PA6795UKMFR9", "A13V1IB3VIYZZH", "APJ6JRA9NG5V4", "A1RKKUPIHCS9HS"}
_local = threading.local()
def session():
if not hasattr(_local, "session"):
_local.session = new_session()
return _local.session
def store(asin: str, marketplace_id: str) -> dict:
row = {"store": STORES[marketplace_id], "listed": None, "new_sellers": None, "amazon": None,
"price": None, "currency": None, "units": None, "note": ""}
try:
o = get_with_retry(session(), "amazon-product-offers", asin=asin, marketplaceId=marketplace_id)
except ApiError as err:
missing = err.status == 404 # 404: the ASIN is not listed on this store
row.update(listed=False if missing else None, note="not listed" if missing else f"error {err.status}")
return row
except requests.RequestException as err:
row["note"] = type(err).__name__
return row
new = [x for x in o.get("offers") or [] if x.get("condition") == "New"]
box = o.get("buyBox") or {}
price = box.get("totalPrice")
row.update(listed=True, new_sellers=len({x.get("sellerId") for x in new}),
amazon=any(x.get("sellerName") == "Amazon" for x in new),
price=round(price, 2) if isinstance(price, (int, float)) and price > 0 else None,
currency=(o.get("currency") or {}).get("code"))
if marketplace_id in WITH_ESTIMATES: # estimates exist on these stores only
try:
row["units"] = get_with_retry(session(), "amazon-product-search-estimated-sells", asin=asin,
marketplaceId=marketplace_id).get("estimated_monthly_sales")
except (ApiError, requests.RequestException):
pass
return row
def verdict(r: dict) -> str:
if r["listed"] is False:
return "not listed yet - you would create the listing"
if r["listed"] is None:
return "unknown - check again"
if not r["new_sellers"]:
return "listed, no New offer right now"
if r["amazon"] or r["new_sellers"] >= 8:
return "crowded"
return "room for another seller" if r["new_sellers"] <= 3 else "competitive"
def expansion(asin: str) -> list[dict]:
with ThreadPoolExecutor(max_workers=5) as pool:
rows = list(pool.map(lambda m: store(asin, m), STORES))
for r in rows:
r["verdict"] = verdict(r)
return rows
if __name__ == "__main__":
for r in expansion("B0CLTBHXWQ"):
print(f"{r['store']:<14} {str(r['price']):>8} {r['currency'] or '':<4} sellers={r['new_sellers']} "
f"amazon={r['amazon']} units={r['units']} {r['verdict']}")
Example result (illustrative values)
amazon.co.uk 399.99 GBP sellers=5 amazon=False units=400 competitive
amazon.de 449.99 EUR sellers=9 amazon=False units=900 crowded
amazon.fr 459.99 EUR sellers=4 amazon=True units=300 crowded
amazon.it 469.99 EUR sellers=2 amazon=False units=250 room for another seller
amazon.es 459.99 EUR sellers=3 amazon=True units=180 crowded
amazon.nl 459.99 EUR sellers=1 amazon=False units=None room for another seller
amazon.com.be None sellers=0 amazon=False units=None listed, no New offer right now
amazon.se None sellers=None amazon=None units=None not listed yet - you would create the listing
amazon.pl None sellers=None amazon=None units=None unknown - check again
amazon.ie None sellers=None amazon=None units=None not listed yet - you would create the listing

How should I read the verdicts?
As a shortlist, not a decision. The thresholds are starting points - adjust them to your category. Seller counts come from the first page of the offer listing, so on busy listings the real number can be higher. "Not listed" can be an opportunity or a sign that the product is restricted there; check the category requirements of that store. Units are missing on NL, BE, SE, PL and IE because the recorded history behind estimates does not cover those stores; there, the store's bestseller list for your category shows whether similar products sell. The Buy Box price gap guide shows what it takes to win the featured offer once you are there.

What the table leaves out
Demand and competition, not the cost of getting there. Storing stock in another country means registering for VAT there, and the fulfilment route - Pan-European FBA or shipping from your home store - changes fees and delivery times. Category and product rules differ by country too. Amazon's Build International Listings tool copies your offers from one store to others in the same region; this table tells you which stores are worth it.
Can I check one store from the command line?
Yes. For a quick look at one store, jq counts distinct New sellers and flags Amazon.
New sellers and Amazon's presence on amazon.it
curl -sG "https://sellermagnet-api.com/api/amazon-product-offers" \
-H "X-Api-Key: $SELLERMAGNET_API_KEY" --max-time 120 \
--data-urlencode "asin=B0CLTBHXWQ" \
--data-urlencode "marketplaceId=APJ6JRA9NG5V4" \
| jq -r 'if .success then ((.data.offers // []) | map(select(.condition == "New"))
| "New sellers: \(map(.sellerId) | unique | length), Amazon: \(any(.[]; .sellerName == "Amazon"))")
else error(.message) end'
Frequently Asked Questions
How do I choose which Amazon marketplace to expand to?
Compare demand and competition for your product on each store: estimated units, number of New sellers and whether Amazon sells it. Few sellers, no Amazon and real demand make a good first step.
What does a 404 on one store mean?
The ASIN is not listed on that store. You would create the listing there instead of joining an existing one; the call is still billed.
Which European stores have sales estimates?
amazon.co.uk, .de, .fr, .it and .es. On .nl, .com.be, .se, .pl and .ie the script shows competition only.
How many credits does one product cost?
About 15 for ten European stores: one offers call per store and one estimate on each of the five stores with estimates.
Are the prices comparable between stores?
Not directly: each is in the store's currency and includes that country's VAT. Convert and remove VAT before comparing.
Bottom line: one offers call per store and an estimate where available turn "where do we launch next" into a table of listing status, competition, Amazon's presence and demand. A free account includes 150 credits - enough for ten products.