The Amazon Japan product API is the same set of endpoints with marketplaceId=A1VC38T7YXB528, the ID of amazon.co.jp. Three things differ from amazon.com: statistics prices are integers in whole yen, not cents, because the yen has no minor unit; the listing date, read from the page's 発売日 (release date) line, can come back with day and month swapped; and titles arrive in Japanese. The script below handles all three for a list of ASINs at 2 credits per ASIN.
Key Takeaways
- amazon.co.jp is marketplaceId A1VC38T7YXB528, and every endpoint accepts it, including the history-based ones: statistics, estimated sales and the ASIN converter.
- Lookup and offers prices are decimal yen (4480.0); statistics prices are integers in minor units, and for JPY that is the yen itself, so never divide them by 100.
- listedSinceDate comes from the page's 発売日 line, written YYYY/M/D; when the day is 12 or lower, day and month can be swapped, so treat such a date as one of two.
- When Amazon itself holds the Buy Box, lookup and offers say "Amazon"; the statistics offers list uses Amazon's Japanese seller ID AN1VRQENFRJN5 instead.
- Lookup plus statistics costs 2 credits per ASIN; malformed ASINs are skipped before they cost anything.
What is different about the Amazon Japan product API?
Nothing in the request: the same endpoints, the same X-Api-Key header and one marketplace ID. The differences are in the data. Prices are in Japanese yen, the lookup's item price is decimal while the statistics series are integers, the listing date comes from a Japanese label, and Amazon appears under two IDs depending on the endpoint. The full list of IDs is in the Amazon marketplace IDs guide.
| Field | On amazon.co.jp | Handle it by |
|---|---|---|
| marketplaceId | A1VC38T7YXB528 (amazon.co.jp, JPY) | pass it on every call |
| lookup and offers prices | decimal yen, e.g. 4480.0, or "N/A" | show without decimals |
| statistics price series | integers in whole yen | never divide by 100 |
| listedSinceDate | YYYY-MM-DD read from the 発売日 line | day 12 or lower: two possible dates |
| Amazon as Buy Box holder | "Amazon" in lookup and offers, AN1VRQENFRJN5 in statistics offers | match both forms |
| title, bulletPoints | Japanese text as on the page | read and store as UTF-8 |
How do I call the Amazon Japan product API in Python?
check() makes two calls per ASIN: /amazon-product-lookup for the title, the current Buy Box item price, the holder and the listing date, and /amazon-product-statistics for the Buy Box price series. to_major() turns minor units into a price with the number of decimals of the currency, which for JPY is zero, and listed() flags a date that can be read two ways. get_with_retry comes from retry.py and ApiError and new_session from sellermagnet.py, both from the Python quickstart. A 401, a 403 or a 503 that survives the retries stops the run, since every remaining ASIN would hit it too; a 404 is reported for its ASIN and the run goes on.
jp_products.py - lookup and statistics on amazon.co.jp, whole yen, flagged dates
import re
import sys
from datetime import date, timedelta
import requests
from retry import get_with_retry
from sellermagnet import ApiError, new_session
MARKETPLACE_ID = "A1VC38T7YXB528" # amazon.co.jp
MINOR_DIGITS = {"A1VC38T7YXB528": 0} # JPY has no minor unit; most other currencies have 2
ASIN_RE = re.compile(r"^[A-Z0-9]{10}$")
STOP = (401, 403, 503) # bad key, no credits, marketplace circuit breaker: stop
RANGE_DAYS = 90
def to_major(value: int, marketplace_id: str) -> float:
"""Statistics prices are integers in minor units: whole yen on amazon.co.jp, cents elsewhere."""
return value / 10 ** MINOR_DIGITS.get(marketplace_id, 2)
def yen(amount: float) -> str:
return f"JPY {amount:,.0f}"
def listed(raw: str | None) -> str:
"""listedSinceDate on amazon.co.jp: day and month can be swapped (the page writes YYYY/M/D)."""
if not raw or not re.fullmatch(r"\d{4}-\d{2}-\d{2}", raw):
return "no date on the page"
y, m, d = raw.split("-")
if int(d) <= 12 and d != m:
return f"{raw} or {y}-{d}-{m} (day and month unclear)"
return raw
def price_range(history: list, today: date) -> str:
"""Low and high of the Buy Box price series over RANGE_DAYS (landed price, minor units)."""
cutoff = (today - timedelta(days=RANGE_DAYS)).isoformat()
values = [p for d, p in history if d >= cutoff]
if not values:
return f"no Buy Box price in {RANGE_DAYS} days"
low, high = to_major(min(values), MARKETPLACE_ID), to_major(max(values), MARKETPLACE_ID)
return f"{RANGE_DAYS}-day Buy Box with shipping {yen(low)} to {yen(high)}"
def check(session, asin: str, today: date) -> list[str]:
info = get_with_retry(session, "amazon-product-lookup", asin=asin, marketplaceId=MARKETPLACE_ID)["productInfo"]
box = info.get("buyBoxInfo") or {}
price = box.get("price") # decimal yen, or "N/A" when nobody holds the Buy Box
shown = yen(price) if isinstance(price, (int, float)) else "no Buy Box"
holder = box.get("sellerId") if box.get("sellerId") not in (None, "N/A") else "none" # "Amazon" = first party
try:
stats = get_with_retry(session, "amazon-product-statistics", asin=asin, marketplaceId=MARKETPLACE_ID)
history = price_range((stats.get("stats") or {}).get("buyBoxPriceHistory") or [], today)
except ApiError as err:
if err.status in STOP:
raise
history = f"no history ({err})" # the lookup result is still worth printing
except requests.RequestException as err:
history = f"no history ({type(err).__name__} after retries)"
return [f"{asin} {(info.get('title') or '?')[:40]}",
f" now {shown} (item price, Buy Box: {holder}), {history}",
f" date first available {listed(info.get('listedSinceDate'))}"]
def main(asins: list[str]) -> int:
session, today = new_session(), date.today()
for asin in dict.fromkeys(a.strip().upper() for a in asins):
if not ASIN_RE.match(asin):
print(f"{asin}: not an ASIN, skipped") # lookups are billed even for a typo
continue
try:
print("\n".join(check(session, asin, today)))
except ApiError as err:
if err.status in STOP:
print(f"stopped at {asin}: {err}")
return 1
print(f"{asin}: {err}") # 404 = no such product on amazon.co.jp (billed)
except requests.RequestException as err:
print(f"{asin}: {type(err).__name__} after retries")
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:] or ["B0EXAMPLJ1", "B0EXAMPLJ2"]))
Output for two ASINs (illustrative ASINs, titles, prices and dates)
$ python jp_products.py B0EXAMPLJ1 B0EXAMPLJ2 # illustrative ASINs, titles and prices
B0EXAMPLJ1 ステンレス製 真空断熱ボトル 500ml
now JPY 4,480 (item price, Buy Box: Amazon), 90-day Buy Box with shipping JPY 3,980 to JPY 4,980
date first available 2024-05-03 or 2024-03-05 (day and month unclear)
B0EXAMPLJ2 ワイヤレスイヤホン Bluetooth 5.3 ノイズキャンセリング
now JPY 12,800 (item price, Buy Box: A3EXAMPLESELLR), 90-day Buy Box with shipping JPY 12,800 to JPY 13,800
date first available 2023-11-28

Why are Amazon Japan prices not divided by 100?
Statistics price series are integers in minor units: 41800 on amazon.com means 418.00 dollars. The yen has no minor unit, so on amazon.co.jp the same integer is the price itself, and dividing by 100 would turn 4,480 yen into 44.80. The lookup and offers endpoints already return decimal yen (4480.0), which only needs formatting without decimals. The series are landed Buy Box prices (item plus shipping), while the lookup price is the item price alone, so the two can differ by the shipping charge. The price history API guide lists every series.
Trimmed lookup response on amazon.co.jp (example values)
{
"success": true,
"data": {
"productInfo": {
"asin": "B0EXAMPLJ1",
"title": "ステンレス製 真空断熱ボトル 500ml",
"buyBoxInfo": {"price": 4480.0, "currencyCode": "JPY", "sellerId": "Amazon"},
"listedSinceDate": "2024-05-03",
"marketplaceId": "A1VC38T7YXB528"
}
}
}
Why can the Date First Available be swapped on amazon.co.jp?
On amazon.co.jp the listing date sits next to the label 発売日 and is written year first, as 2024/3/5 for 5 March 2024. The API reads dates day first, the order most European pages use, so that date comes back as 2024-05-03. A day above 12 cannot be a month, so 2024/3/15 comes back correctly as 2024-03-15. listed() therefore marks every Japanese date whose day is 12 or lower (and differs from the month) as one of two dates, and leaves the rest alone. Use such a date for a rough age, not for day-exact math. On English pages the same field reads the Date First Available line, the day the ASIN was created; on amazon.co.jp it is the release date the page shows.

How many credits does the script use?
Two per ASIN: one lookup and one statistics call. A 404 on the lookup is billed and skips the statistics call for that ASIN, a 502 or 503 is billed on every attempt of get_with_retry, a 500 is refunded, and the free gate errors (400 for a missing parameter, 401, 403, 429) cost nothing. To compare the same product across stores, the cross-marketplace price comparison runs one lookup per marketplace; plans are on Pricing.
Frequently Asked Questions
What is the marketplace ID for Amazon Japan?
A1VC38T7YXB528 is amazon.co.jp. Pass it as marketplaceId on every call; prices come back in Japanese yen (JPY).
Are Amazon Japan prices in cents?
No. Lookup and offers return decimal yen such as 4480.0. Statistics returns integers in minor units, and since the yen has none, 4480 already means 4,480 yen.
Why does Date First Available look wrong for some Japanese products?
The page writes the date as YYYY/M/D and the API reads it day first, so 2024/3/5 can come back as 2024-05-03. Dates with a day above 12 are not affected.
How do I see if Amazon itself sells a product on amazon.co.jp?
In lookup and offers the Buy Box sellerId is the literal "Amazon", and offers add amazonSellerId. In the statistics offers list Amazon appears under its Japanese seller ID AN1VRQENFRJN5.
Do product titles come back in Japanese?
Yes, titles and bullet points come back in Japanese as they appear on amazon.co.jp. Read the JSON as UTF-8 and store it as UTF-8 so the characters survive.
Bottom line: on amazon.co.jp keep the yen whole, treat a listing date with a day of 12 or lower as one of two dates, and look for Amazon under both "Amazon" and AN1VRQENFRJN5. A free account includes 150 credits, enough for 75 ASINs with this script.