Product identifier extraction is one of the most important—and often underestimated—parts of e-commerce data collection. Product names can change between retailers, descriptions can be rewritten, and the same item may appear under different titles across marketplaces. Identifiers such as SKU, GTIN, UPC, EAN, and MPN provide a more reliable way to determine what a product actually is.
For teams collecting product data at scale, these identifiers can support product matching, catalog enrichment, assortment analysis, duplicate detection, and cross-retailer comparisons.
The difficult part is extraction.
Product identifiers may appear in visible specification tables, JSON-LD, embedded JavaScript objects, HTML attributes, variant selectors, or dynamically loaded API responses. Worse, a single product page may contain identifiers for several variants at the same time.
A reliable extraction system therefore needs to do more than search the page for a sequence of numbers. It needs to identify the type of identifier, associate it with the correct product or variant, validate its format, and preserve evidence showing where the value came from.
This guide explains how to build that process.
What Are SKU, GTIN, UPC, EAN, and MPN?
Before extracting product identifiers, it is important to understand that these fields are not interchangeable.
| Identifier | Typical meaning | Scope |
|---|---|---|
| SKU | Stock Keeping Unit | Usually retailer or seller specific |
| GTIN | Global Trade Item Number | Standardized global product identifier |
| UPC | Universal Product Code | Common GTIN representation, especially in North America |
| EAN | European Article Number / International Article Number | Common retail identifier format |
| MPN | Manufacturer Part Number | Assigned by the manufacturer |
The distinction matters when building a product database.
A retailer’s SKU may uniquely identify an item inside that retailer’s catalog but have no meaning on another website. An MPN can be useful for matching manufacturer-defined products across sellers, while GTIN-family identifiers are designed to provide standardized trade-item identification.
For this reason, a good extraction pipeline should preserve the identifier type instead of putting every discovered code into a generic product_id field.
A structured record might look like:
{
"sku": "WH-1000XM5-BLK",
"gtin": "0123456789012",
"mpn": "WH1000XM5/B",
"brand": "Example Brand",
"variant": "Black",
"source_url": "https://example.com/product"
}
The exact schema depends on the source and product category, but keeping these concepts separate makes downstream matching considerably safer.
Why Product Identifier Extraction Is Harder Than It Looks
On a simple product page, an identifier might appear as:
SKU: ABC-12345
Real e-commerce websites are rarely that consistent.
One retailer may call the same field Item Number, another Product Code, and another Model Number. Some websites expose an identifier only in structured metadata, while others load it after the user selects a size or color.
There is another important problem: the identifier visible on the page may not belong to the currently selected variant.
Imagine a shoe page containing 12 sizes and five colors. The HTML or application state could contain dozens of SKU values. Extracting the first SKU found in the document would produce technically valid data but potentially associate it with the wrong product variant.
This is why identifier extraction should be treated as an entity-resolution problem rather than simple text scraping.
Where Product Identifiers Usually Appear
A robust extractor should inspect several possible data layers instead of relying on a single CSS selector.
1. Visible Product Information
The simplest source is the visible page itself.
Identifiers commonly appear under sections such as:
Product Details
Specifications
Technical Information
Additional Information
Model Information
For example:
<div class="product-spec">
<span class="label">SKU</span>
<span class="value">ABC-12345</span>
</div>
This data is relatively easy to extract because the label provides semantic context.
However, visible content should not automatically be considered authoritative. Some pages show a parent product number while individual variants use different identifiers internally.
2. HTML Attributes
Product identifiers sometimes appear in HTML attributes even when they are not displayed directly to users.
For example:
<div
class="product"
data-sku="ABC-12345"
data-product-id="847291">
</div>
Variant controls may contain even more useful information:
<button
data-color="black"
data-size="42"
data-sku="SHOE-BLK-42">
42
</button>
In this case, the relationship between the SKU and the variant is more valuable than the SKU alone.
An extraction pipeline should therefore preserve nearby attributes such as size, color, model, capacity, and seller whenever possible.
3. JSON-LD Structured Data
JSON-LD is often one of the first places worth checking because many e-commerce websites publish structured product information for search engines.
A page may contain:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Example Wireless Headphones",
"sku": "WH-1000-BLK",
"mpn": "WH1000B",
"gtin13": "0123456789012"
}
</script>
Instead of parsing presentation-oriented HTML, the extractor can parse the JSON directly.
A basic Python example:
import json
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
for script in soup.find_all(
"script",
attrs={"type": "application/ld+json"}
):
try:
data = json.loads(script.string or "")
except (json.JSONDecodeError, TypeError):
continue
print(data)
Production implementations need additional logic because a JSON-LD block may contain an object, an array, or an @graph containing several entities.
The presence of structured data also does not guarantee that it is current or variant-specific. It still needs validation against the page context.
Understanding GTIN Fields in Structured Data
When processing structured product metadata, you may encounter fields such as:
gtin
gtin8
gtin12
gtin13
gtin14
Rather than treating each field as a completely different identifier system, it is useful to normalize them under a GTIN model while preserving their original representation.
For example:
{
"identifier_type": "gtin13",
"raw_value": "0123456789012",
"normalized_value": "0123456789012"
}
Do not convert identifier strings to integers.
A leading zero can be meaningful, and converting a value such as:
0123456789012
into a numeric type could turn it into:
123456789012
That changes the identifier.
Product identifiers should generally be stored as strings.
4. Embedded JavaScript and Application State
Modern e-commerce websites often embed product data in JavaScript so frontend applications can render the page.
For example:
window.__PRODUCT__ = {
"id": "847291",
"sku": "ABC-12345",
"mpn": "ABC12345-B",
"variants": [
{
"color": "black",
"sku": "ABC-BLK"
},
{
"color": "white",
"sku": "ABC-WHT"
}
]
};
Framework-based websites may also expose serialized application state in script elements.
The exact implementation varies by platform, so an extractor should not assume that every website uses the same variable or framework.
When structured application state is available and permitted to be processed, it can be useful because it often preserves relationships between products and their variants more clearly than the rendered DOM.
5. Browser Network Responses
Sometimes the identifier is not present in the initial HTML at all.
A JavaScript application may request product information after the page loads:
Browser
↓
Product Page
↓
XHR / fetch
↓
Product API
↓
JSON
For browser-based collection, Playwright can observe responses generated during the normal page session.
For example:
page.on('response', async response => {
const contentType =
response.headers()['content-type'] || '';
if (!contentType.includes('application/json')) {
return;
}
try {
const data = await response.json();
// Process relevant product responses here.
} catch {
// Ignore responses that cannot be parsed as JSON.
}
});
In a production system, do not treat every JSON response as product data. Filter responses using known request patterns, response schemas, or expected fields.
This approach can be particularly useful when selecting a variant causes the website to request updated product information.
Extracting Identifiers in the Right Order
Instead of applying dozens of regular expressions to the entire HTML document, use a source hierarchy.
A practical pipeline might be:
Official structured source
↓
JSON-LD
↓
Embedded product state
↓
Variant data
↓
Visible specifications
↓
DOM attributes
↓
Carefully constrained text extraction
The exact priority should be source-specific.
The important principle is to prefer sources where the semantic relationship between the identifier and product is explicit.
Finding the number is easy. Proving what that number identifies is the difficult part.
Do Not Identify UPC or EAN by Length Alone
One of the most common mistakes in product identifier extraction is assuming that every 12-digit number is a UPC or every 13-digit number is an EAN.
Product pages contain many numeric values:
Order numbers
Internal database IDs
Phone numbers
Dates
Prices
Serial references
Dimensions
Tracking parameters
A numeric pattern is therefore only a candidate.
Instead of:
13 digits → EAN
use contextual evidence:
13-digit candidate
+
Nearby "EAN" or GTIN label
+
Valid checksum
+
Correct product context
=
High-confidence identifier
This dramatically reduces false positives.
Validate GTIN-Family Check Digits
GTIN-family identifiers use a check digit that can help detect malformed candidates.
For a GTIN candidate, the final digit can be checked against a value calculated from the preceding digits using the GTIN weighting rules.
Here is a simple Python validator:
def valid_gtin(value):
if not value.isdigit():
return False
if len(value) not in (8, 12, 13, 14):
return False
digits = [int(x) for x in value]
check_digit = digits[-1]
body = digits[:-1]
total = 0
for position, digit in enumerate(reversed(body), start=1):
weight = 3 if position % 2 == 1 else 1
total += digit * weight
expected = (10 - total % 10) % 10
return check_digit == expected
Checksum validation is useful, but it does not prove that the identifier belongs to the product being collected.
A random numeric string can theoretically satisfy the checksum. Context and product association are still required.
SKU Requires Different Logic
SKU extraction is fundamentally different from GTIN validation because SKU formats are retailer-specific.
A SKU might look like:
12345678
ABC-123
SHOE-BLK-42
P1000-US-B
There is no universal SKU length or checksum.
Instead, extraction should depend heavily on labels and structured context.
Good evidence includes:
SKU
Seller SKU
Item SKU
Variant SKU
Stock Code
But even labels need interpretation. Product ID, Item Number, or Article Number may represent a SKU on one website and something entirely different on another.
For frequently collected domains, maintain a source-specific mapping rather than forcing every label into a universal rule.
MPN Extraction Requires Manufacturer Context
MPN is useful for product matching because it is intended to identify a manufacturer’s product or part.
However, websites may use labels such as:
MPN
Manufacturer Part Number
Model
Model Number
Part Number
Manufacturer Number
These labels are not always equivalent.
For example, a model family could be:
ThinkPad X1 Carbon
while an actual manufacturer part number identifies a particular configuration.
When possible, store both:
{
"model": "Example Model X",
"mpn": "21AB0012US"
}
Avoid automatically converting every Model Number into an MPN unless you understand the source’s terminology.
The Hardest Problem: Product Variants
Variant handling is where many large-scale product extraction systems fail.
Consider a page selling a T-shirt in:
Black / Small
Black / Medium
Black / Large
White / Small
White / Medium
White / Large
The page may have one parent product identifier and six variant SKUs.
A flat extractor might return:
{
"product": "Example T-Shirt",
"sku": "TSHIRT-BLK-S"
}
But this loses the fact that the SKU belongs specifically to the Black / Small variant.
A better structure is:
{
"product": "Example T-Shirt",
"parent_id": "TSHIRT-001",
"variants": [
{
"color": "Black",
"size": "Small",
"sku": "TSHIRT-BLK-S"
},
{
"color": "Black",
"size": "Medium",
"sku": "TSHIRT-BLK-M"
}
]
}
This becomes extremely important when comparing the same product across retailers.
Build an Evidence-Based Identifier Model
For serious product intelligence systems, storing only the final identifier is often insufficient.
Instead, store evidence about how it was discovered.
For example:
{
"type": "gtin13",
"value": "0123456789012",
"source": "json_ld",
"variant": "black",
"validated": true,
"confidence": 0.98
}
The confidence value should come from explicit rules or a documented model rather than an arbitrary number.
A system might assign greater confidence when an identifier:
- Appears in a structured product object.
- Has an explicit identifier label.
- Passes the appropriate format validation.
- Matches the selected variant.
- Appears consistently across multiple independent page representations.
Conflicting values should be preserved for investigation rather than silently overwritten.
Separate Extraction From Product Matching
Extracting identifiers and deciding whether two listings represent the same product are related but different problems.
Imagine two retailers produce:
{
"title": "Example Headphones Black",
"mpn": "WH1000-B",
"gtin": "0123456789012"
}
and:
{
"title": "Example Wireless Headphones - Black",
"mpn": "WH1000-B",
"gtin": "0123456789012"
}
The shared identifiers provide strong evidence that the listings refer to the same trade item.
But another listing might have:
{
"title": "Example Headphones Black",
"mpn": null,
"gtin": null
}
Now matching may require additional attributes such as brand, model, capacity, dimensions, or variant information.
For this reason, the collection pipeline should preserve as many trustworthy identity signals as possible rather than attempting to create a universal product key during extraction.
A Better Data Schema for Product Identifiers
For larger projects, consider separating product information from identifier observations.
For example:
{
"product": {
"brand": "Example Brand",
"name": "Wireless Headphones",
"variant": "Black"
},
"identifiers": [
{
"type": "sku",
"value": "WH-BLK-001",
"scope": "retailer",
"source": "variant_data"
},
{
"type": "mpn",
"value": "WH1000-B",
"scope": "manufacturer",
"source": "specification_table"
},
{
"type": "gtin13",
"value": "0123456789012",
"scope": "trade_item",
"source": "json_ld"
}
]
}
This model makes it easier to preserve multiple identifiers without pretending they all serve the same purpose.
It also allows downstream systems to select the most appropriate identifier for catalog matching, deduplication, or analytics.
Handling Missing Product Identifiers
Not every product page provides a GTIN, UPC, EAN, or MPN.
A missing identifier should remain missing:
{
"gtin": null
}
Do not attempt to infer a GTIN from unrelated numeric fields or manufacture one from a retailer SKU.
It is useful to distinguish between:
not_found
not_provided
not_applicable
extraction_failed
These states have different meanings.
If extraction failed because a page did not load correctly, the system may retry. If the manufacturer simply does not assign a particular identifier, retrying will not solve the problem.
Monitoring Extraction Quality at Scale
Once identifier extraction runs across thousands or millions of product pages, individual manual checks are no longer sufficient.
Monitor metrics such as:
SKU extraction rate
GTIN extraction rate
MPN extraction rate
Checksum failure rate
Variant association failure rate
Conflicting identifier rate
Pages with zero identifiers
Sudden changes can reveal extraction problems.
For example, if a retailer normally provides SKU values on 96% of collected product pages and that rate suddenly falls to 18%, it is unlikely that most products lost their SKUs overnight. The page structure or extraction logic may have changed.
These metrics turn identifier extraction into an observable data pipeline rather than a collection script that silently produces bad data.
Product Identifier Extraction Across Multiple Markets
International product collection introduces another layer of complexity.
The same product may appear under different retailer SKUs across countries. Some variants may be region-specific, and packaging or regulatory differences can result in different trade-item identifiers.
This means a product database should avoid assuming:
Same product name = same identifier
or:
Same brand + model = same sellable variant
Preserve market, retailer, variant, and identifier context separately.
For example:
{
"market": "JP",
"retailer": "example-retailer",
"sku": "JP-847291",
"mpn": "ABC1000-JP",
"gtin": "0123456789012"
}
This makes cross-market analysis much more defensible.
Where Proxy Infrastructure Fits Into Product Data Collection
When product data is collected across multiple permitted websites or geographic markets, the network layer can affect what the collection system observes.
Retail websites may present different catalogs, product variants, availability, currencies, or localized content depending on the market being accessed.
Proxy infrastructure can be one component of a geographically distributed product collection system.
For example, a broader architecture may look like:
Target Market
↓
Collection Session
↓
Product Page
↓
HTML / Structured Data / Browser Response
↓
Identifier Extraction
↓
Validation
↓
Variant Resolution
↓
Product Dataset
ColaProxy provides proxy infrastructure that developers can evaluate for permitted web data collection and automation workflows, including scenarios where geographic targeting or session continuity is required.
The proxy layer, however, should remain separate from the identification layer. A successful request does not guarantee that the correct product identifier has been extracted.
Network reliability, extraction accuracy, and product identity should be monitored independently.
Common Product Identifier Extraction Mistakes
One of the biggest mistakes is treating every long number as a GTIN. Length is useful for identifying candidates, but contextual and checksum validation should follow.
Another is storing identifiers as numeric database fields. Identifiers are labels, not quantities, and leading zeros must be preserved.
Variant confusion is equally dangerous. A valid SKU associated with the wrong size, color, or configuration can create incorrect product matches downstream.
Finally, avoid collapsing SKU, MPN, UPC, EAN, and GTIN into a single field. They have different scopes and should remain distinguishable throughout the data pipeline.
Conclusion
Extracting SKU, GTIN, UPC, EAN, and MPN from product pages is not simply a matter of finding numbers in HTML.
A reliable product identifier extraction system needs to understand where the identifier came from, what type of identifier it represents, which product or variant it belongs to, and whether its format can be validated.
The strongest pipelines combine structured metadata, visible specifications, variant information, application data, and browser responses while preserving source evidence for every extracted identifier.
For large-scale e-commerce data projects, these identifiers provide the foundation for more advanced tasks such as product matching, catalog deduplication, assortment analysis, cross-retailer comparison, and market intelligence.
And when product collection spans multiple permitted websites or geographic markets, infrastructure such as ColaProxy can support the collection layer while identifier validation and product matching ensure that the resulting dataset remains meaningful.
Frequently Asked Questions
What is the best way to extract SKU from a product page?
Start with structured product data, variant objects, explicit SKU labels, and relevant HTML attributes. Because SKU formats are retailer-specific, avoid relying only on regular expressions.
Can I identify a UPC or EAN based only on the number of digits?
No. Length can identify possible candidates, but it does not prove what a number represents. Use labels, structured metadata, product context, and appropriate check-digit validation.
Should GTIN, UPC, and EAN be stored as numbers?
No. Store product identifiers as strings so leading zeros and exact formatting are preserved.
Why do product pages contain multiple SKUs?
Many product pages represent a product family with several variants. Each size, color, capacity, or configuration may have its own SKU.
Where should I look for product identifiers first?
Check structured sources such as JSON-LD and product or variant data, then inspect visible specifications and HTML attributes. For JavaScript applications, product information may also appear in responses generated during the browser session.
Can product identifiers be used to match products across retailers?
Yes, they can provide strong matching signals, particularly standardized identifiers and manufacturer-defined part numbers. However, identifiers should still be checked against brand, model, variant, and market context.