Skip to main content

ProductMapper Python SDK: UPC to ASIN Lookup API Client

PyPI version Python versions PyPI downloads CI Typed Ruff License: MIT

Official Python client for the ProductMapper API. Convert a UPC, EAN, GTIN, ASIN or product title into live Amazon listing data: price, sales rank (BSR), offer counts, Buy Box status, brand, category and images, across 16 Amazon marketplaces.

Use it to build barcode to ASIN lookup, retail arbitrage tooling, competitor price monitoring, catalog enrichment, and product data pipelines, with sync and async clients and full type hints.

Website - API Documentation - Get a Free API Key - Node.js SDK

Contents

Why ProductMapper

Feature Detail
Identifier types UPC, EAN, GTIN, ASIN, free-text title, or auto detection
Amazon marketplaces 16 regions including US, CA, UK, DE, FR, IT, ES, JP, AU, IN
Batch size Up to 500 identifiers per background job, with CSV export
Data returned Price, list price, sales rank, offer counts, FBA/merchant split, Buy Box, brand, category, images
Clients Synchronous and asyncio, both fully type hinted
Python 3.9 through 3.13

Install

pip install productmapper
uv add productmapper
# or
poetry add productmapper

Requires Python 3.9 or newer. Ships py.typed for full editor and mypy support.

Quick start

import os
from productmapper import ProductMapper

client = ProductMapper(api_key=os.environ["PRODUCTMAPPER_API_KEY"])

result = client.lookup(value="753933140816", type="UPC")

print(result.marketplace_id)                  # "B09Z2J1MP2" (the matched ASIN)
print(result.title)                           # "Husky Liners Weatherbeater Floor Mats"
print(result.price)                           # 80.99
print(result.listing_details.sales_rank)      # 67364

Get a free API key at product-mapper.com/dashboard/api-keys. Keys look like pm_live_... and belong in an environment variable, never in source control.

The client is also a context manager, which closes the connection pool on exit:

with ProductMapper(api_key=...) as client:
    result = client.lookup(value="753933140816")

Convert UPC to ASIN

type defaults to auto, so the server detects whether you passed a UPC, EAN, GTIN or ASIN.

client.lookup(value="753933140816")                            # auto-detected
client.lookup(value="753933140816", type="UPC")                # UPC to ASIN
client.lookup(value="0885909950805", type="EAN")               # EAN to ASIN
client.lookup(value="B09Z2J1MP2", type="ASIN")                 # ASIN lookup
client.lookup(value="Logitech MX Master 3S", type="Title")     # title search
client.lookup(value="753933140816", region="DE")               # scope to one marketplace

Each successful mapping costs one credit. Without a region, an identifier that matches in several Amazon marketplaces returns them all, and still costs a single credit. Use .matches to handle the one-match and many-match cases the same way:

result = client.lookup(value="753933140816")

for match in result.matches:
    print(match.amazon_marketplace_label, match.listing_details.formatted_price)

Full listing fields

listing = result.listing_details

listing.asin                   # "B09Z2J1MP2"
listing.title                  # product title
listing.brand                  # "Husky Liners"
listing.price                  # 80.99
listing.list_price             # 89.99
listing.formatted_price        # "$80.99"
listing.sales_rank             # 67364  (Best Sellers Rank)
listing.offer_count            # 5
listing.offer_count_fba        # 1
listing.offer_count_merchant   # 4
listing.is_buy_box_winner      # True
listing.category               # "Floor Mats"
listing.category_group         # "Automotive Parts and Accessories"
listing.image_url              # product image
listing.link                   # Amazon product URL

Any field the API adds later is still reachable through listing.raw["newField"].

Slow lookups

If a lookup takes more than 8 seconds the API returns a job instead of a result. The client polls that job automatically, so lookup() always returns a result. To manage polling yourself:

queued = client.lookup(value="753933140816", poll=False)

if queued.status == "processing":
    result = client.wait_for_job(queued.job_id)

Bulk UPC to ASIN conversion

Submit up to 500 identifiers as one background job:

job = client.lookup_many(["753933140816", "B09Z2J1MP2", "Logitech MX Master 3S"])

finished = client.wait_for_batch(
    job.id,
    on_progress=lambda j: print(f"{j.processed_items}/{j.total_items}"),
)

for item in finished.items:
    print(item.identifier_value, item.title, item.price, item.status)

Export results as CSV, ready for Excel or Google Sheets:

from pathlib import Path

csv_text = client.get_batch_csv(job.id)
Path("asin-results.csv").write_text(csv_text, encoding="utf-8")

Batch rows carry fewer fields than a single lookup. Look an identifier up individually when you need link, category, identifiers or the full offer breakdown.

Lookup history

Every lookup is recorded, 25 rows per page.

page = client.history(page=1, search="husky")
print(page.total, page.total_pages)

for row in page:
    print(row.identifier_value, row.title, row.status)

# Or walk every page, one row at a time.
for row in client.history_all():
    print(row.identifier_value)

client.delete_history_row(row_id)
client.clear_history()

History rows report status as success or not_found, while batch items report completed.

Async client

AsyncProductMapper mirrors the sync client method for method.

import asyncio
from productmapper import AsyncProductMapper

async def main():
    async with AsyncProductMapper(api_key=...) as client:
        result = await client.lookup(value="753933140816", type="UPC")
        print(result.title)

        # Resolve many identifiers concurrently.
        results = await asyncio.gather(
            *(client.lookup(value=v) for v in ["753933140816", "B09Z2J1MP2"]),
            return_exceptions=True,
        )

        async for row in client.history_all():
            print(row.identifier_value)

asyncio.run(main())

Error handling

Every failure is a ProductMapperError, so one except can cover them all, with subclasses for the cases worth handling individually.

from productmapper import (
    NotFoundError,
    RateLimitError,
    CreditsExhaustedError,
)

try:
    result = client.lookup(value="753933140816")
except NotFoundError:
    print("No match in the Amazon catalog.")
except CreditsExhaustedError:
    print("Out of credits: upgrade the plan or buy a credit pack.")
except RateLimitError as exc:
    print(f"Retry in {exc.retry_after}s, limit is {exc.limit}/min")
Exception HTTP Raised when
ValidationError 400 Bad arguments, rejected before or by the API
AuthenticationError 401 API key missing, malformed or revoked
PermissionError 403 No active organization selected
CreditsExhaustedError 403 Credit balance is empty
NotFoundError 404 No catalog match, or the resource is not yours
RateLimitError 429 Plan requests-per-minute exceeded
ServerError 5xx The API failed to handle the request
TimeoutError - A request or polling loop ran out of time
ConnectionError - The request never reached the API
JobFailedError - A queued lookup or batch ended in a failed state

Rate limits, server errors and network failures are retried automatically with exponential backoff, honoring Retry-After. Validation and auth failures are never retried.

PermissionError, TimeoutError and ConnectionError deliberately shadow the builtins of the same name. Import them from productmapper to catch the API versions.

Configuration

client = ProductMapper(
    api_key=os.environ["PRODUCTMAPPER_API_KEY"],
    timeout=30.0,                            # per request, in seconds
    max_retries=2,                           # for 429, 5xx and network errors
    headers={"X-Team": "pricing"},           # sent with every request
)

API reference

Method Description
lookup(value, ...) Resolve one identifier. Polls a queued lookup unless poll=False
lookup_many(items, ...) Submit up to 500 identifiers as a batch job
get_job(job_id) Poll one queued single lookup
get_jobs(job_ids) Poll up to 100 queued lookups in one round trip
get_batch(batch_id) Fetch a batch job and its items
get_batch_csv(batch_id) Export a batch job as CSV
wait_for_job(job_id, ...) Poll a queued lookup until it resolves
wait_for_batch(batch_id, ...) Poll a batch until every item is processed
history(page=1, search=None) List lookup history, 25 per page
history_all(search=None) Iterator over every history row
delete_history_row(row_id) Delete one history row
clear_history() Clear the entire history

Identifier types: auto, UPC, EAN, GTIN, ASIN, Title

Amazon marketplaces: US, CA, MX, BR, UK, DE, FR, IT, ES, NL, PL, SE, IN, JP, AU, SG

Both are exported as IDENTIFIER_TYPES and REGIONS.

Examples

Runnable scripts live in examples/: single lookup, batch with progress and CSV export, history paging, async usage, and full error handling.

FAQ

How do I convert a UPC to an ASIN in Python? Install the package, create a client with your API key, and call client.lookup(value="<upc>", type="UPC"). The matched ASIN is result.marketplace_id.

Can I look up many barcodes at once? Yes. lookup_many() accepts up to 500 identifiers per batch job, and get_batch_csv() exports results as CSV.

Does it support asyncio? Yes. AsyncProductMapper mirrors the sync client method for method.

Which Amazon marketplaces are supported? 16 regions, listed above. Pass region to scope a lookup, or omit it to search across regions.

Does it work with pandas? Yes. Batch items and history rows expose plain attributes and a raw dict, so pd.DataFrame([item.raw for item in job.items]) works directly.

Is there a free plan? Yes, see pricing.

Is there a Node.js version? Yes, @siktec-lab/productmapper on npm (source).

License

MIT, see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

productmapper-1.2.1.tar.gz (17.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

productmapper-1.2.1-py3-none-any.whl (19.5 kB view details)

Uploaded Python 3

File details

Details for the file productmapper-1.2.1.tar.gz.

File metadata

  • Download URL: productmapper-1.2.1.tar.gz
  • Upload date:
  • Size: 17.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for productmapper-1.2.1.tar.gz
Algorithm Hash digest
SHA256 3076ece81adc8d90f2c71be9a11a902ef92ea75f0e3218e8dc5ed5664880568f
MD5 78dc9a1c1d5512aaa2369444b63c9dd4
BLAKE2b-256 3174404070de0d0cb5997a0dae5a4d21372252110d00a393a74e9a3b934fe2d0

See more details on using hashes here.

Provenance

The following attestation bundles were made for productmapper-1.2.1.tar.gz:

Publisher: release.yml on siktec-lab/product-mapper-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file productmapper-1.2.1-py3-none-any.whl.

File metadata

  • Download URL: productmapper-1.2.1-py3-none-any.whl
  • Upload date:
  • Size: 19.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for productmapper-1.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 de256180dffda93841bedca651bc00563effc04a95930002da0fa2871564b29e
MD5 639a7f66370bf0e5a3be5f36595a25b0
BLAKE2b-256 e2f7fd82eb83f45be40ec8c873db1e6306e0d9ace2e59438057e70a7c236ae52

See more details on using hashes here.

Provenance

The following attestation bundles were made for productmapper-1.2.1-py3-none-any.whl:

Publisher: release.yml on siktec-lab/product-mapper-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

1.2.1 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page