# EAN-13 Barcode Validator (`automation-lab/ean-13-check-digit-validator`) Actor

Validate EAN-13 barcode batches or calculate check digits for 12-digit bases. Export normalized strings, format status, expected and supplied digits, validity and errors for catalog quality control.

- **URL**: https://apify.com/automation-lab/ean-13-check-digit-validator.md
- **Developed by:** [Automation Lab](https://apify.com/automation-lab) (community)
- **Categories:** E-commerce, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.72 / 1,000 item extracteds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## EAN-13 Barcode Validator

Run an **ean 13 barcode check** on supplied product-code batches before catalog imports, marketplace syndication or supplier-data reconciliation. Validate a complete 13-digit code or calculate the missing check digit from a 12-digit base. Export one structured result per processed input, including errors.

This is an algorithm-only utility, not a product scraper. It does not check whether a barcode is assigned by GS1, belongs to a particular product, or is authentic.

### Who is it for?

- Catalog operations teams screening supplier barcode columns before an import.
- Retail data engineers building repeatable checksum checks into a pipeline.
- Merchants identifying likely transcription errors before marketplace submission.
- Analysts who need explicit per-row error reasons rather than a single batch verdict.

### Why use it?

Keep leading zeros, original input positions and duplicates intact. A checksum mismatch is distinguished from a malformed code, and both appear in the same export as successful checks. Calculation mode produces a completed code without falsely claiming to have verified a supplied check digit.

The Actor uses no external product database, account, proxy or supplier API. Its result is deterministic for a given string, apart from the processing timestamp. Invalid individual codes do not discard the rest of the batch.

### Getting started

1. Open the Actor input form.
2. Enter barcode **strings**, not JSON numbers, in `codes`.
3. Select `validate` for full 13-digit codes or `calculate` for 12-digit bases.
4. Set `maxItems` if you want only the first part of the batch.
5. Run the Actor and open the default dataset.
6. Export JSON, CSV or Excel-compatible data using Apify's dataset export controls.

```json
{
  "codes": ["4006381333931", "4006381333932", "0123456789012"],
  "mode": "validate",
  "maxItems": 10000
}
```

The first and third checks pass; the second has an incorrect supplied check digit.

### Input parameters

| Field | Default | Behavior |
|---|---|---|
| `codes` | Required | Array of 1–10000 strings, each at most 256 characters |
| `mode` | `validate` | Whole-batch operation: `validate` or `calculate` |
| `maxItems` | `20` | Global first-N input-entry cap, from 1 to 10000 |

Leading and trailing whitespace is trimmed. Internal spaces, hyphens, letters and non-ASCII digits are rejected, not silently removed. Zero is not an unlimited setting. Duplicates and invalid entries count toward the cap. The platform charge budget can stop output before the cap.

Unknown input fields, non-string array entries, empty arrays and unsupported modes fail the run with a clear error. There are no URL, file-upload, CSV-input or dataset-import routes: provide the array directly, or prepare it in your upstream application.

### EAN-13 barcode check rules

A valid-format EAN-13 contains exactly thirteen ASCII digits. The first twelve digits are weighted alternately 1 and 3 from the left. The expected final digit is `(10 - (weightedSum % 10)) % 10`.

Validation compares that expected digit with the supplied thirteenth digit. A matching checksum detects many transcription errors, but not all errors; some digit transpositions can remain checksum-valid.

An all-zero string passes the checksum mathematically. It is not evidence of a legitimate assigned retail identifier. Product assignment, restricted prefixes and business-specific forbidden values belong in separate catalog rules.

### Calculate a missing check digit

Use exactly twelve digits per entry:

```json
{
  "codes": ["400638133393", "012345678901"],
  "mode": "calculate"
}
```

The results contain completed codes `4006381333931` and `0123456789012`. In this mode `providedCheckDigit` and `isValid` are null: there is no supplied check digit to verify. A thirteen-digit entry is a format error in calculation mode; the Actor never guesses a mode per row.

### Output fields

| Field | Meaning |
|---|---|
| `inputIndex` | Zero-based position in the original input array |
| `inputCode` | Original string, unchanged |
| `normalizedCode` | String after trimming surrounding whitespace |
| `mode` | Selected batch operation |
| `formatStatus` | `valid_format` or `invalid_format`, independent of checksum match |
| `calculatedCheckDigit` | Expected digit as a string; null for invalid format |
| `providedCheckDigit` | Supplied final digit in valid-format validation; otherwise null |
| `completedCode` | Base plus expected digit; null for invalid format |
| `isValid` | Validation verdict; null for calculation mode |
| `errorReason` | Machine-readable diagnostic; null when successful |
| `checkedAt` | UTC ISO 8601 processing timestamp |

On a mismatch, `completedCode` is the checksum-corrected candidate. It does **not** establish which original digit was mistyped or justify automatically replacing the catalog code.

```json
{
  "inputIndex": 0,
  "inputCode": "4006381333931",
  "normalizedCode": "4006381333931",
  "mode": "validate",
  "formatStatus": "valid_format",
  "calculatedCheckDigit": "1",
  "providedCheckDigit": "1",
  "completedCode": "4006381333931",
  "isValid": true,
  "errorReason": null,
  "checkedAt": "2026-10-28T12:00:00.000Z"
}
```

The timestamp above is illustrative; all other values match the supplied example's computed result.

### Errors and limits

- `empty_code`: nothing remains after trimming.
- `non_ascii_digit`: characters other than ASCII 0–9 are present.
- `expected_13_digits`: validation received the wrong digit count.
- `expected_12_digits`: calculation received the wrong digit count.
- `check_digit_mismatch`: format is valid but the final digit is incorrect.

Format diagnostics follow that order: a code containing letters reports non-digit content before length. Validation format errors have `isValid: false`; calculation format errors retain `isValid: null`. Every such returned row is billable.

There is no deduplication, pagination or automatic retry against outside services. Larger catalogs can be partitioned into separate batches of up to 10000 entries. Use the original array position to join results back to the source; positions restart for each run.

### How much does it cost to validate EAN-13 barcodes?

Pay per event: one **start** event per accepted run and one **item** event per returned row, whether the code is valid, invalid or duplicated. Both operations use the same events. No separate calculation fee applies.

The current BRONZE price is **$0.001 per run plus $0.0012 per processed barcode**. For example:

| Returned rows | BRONZE total |
|---:|---:|
| 1 | $0.0022 |
| 10 | $0.013 |
| 100 | $0.121 |

Prices vary by Apify plan tier; see the Actor's current pricing panel. A partial run can incur charges for its emitted rows. Malformed batch configuration is rejected before the start charge. No subscription, outside lookup fee or proxy purchase is required by this Actor.

### Integrations

- In a supplier-import job, convert the barcode column into strings, run validation, then quarantine rows with `isValid: false`.
- Use Apify schedules to recheck newly supplied batches. Scheduling repeats the saved input; this Actor does not discover changed records or keep a historical catalog.
- Export CSV to Excel or Google Sheets, configuring barcode columns as text to avoid stripping leading zeros.
- Use an Apify webhook to notify a downstream application when a run completes, then fetch its dataset and join by `inputIndex`.
- Combine checksum screening with a separate product lookup when you need product metadata, rather than treating checksum success as identity verification.

### API usage

Start a run with your own Apify token:

```bash
curl -X POST 'https://api.apify.com/v2/acts/automation-lab~ean-13-check-digit-validator/runs' \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"codes":["4006381333931"],"mode":"validate"}'
```

JavaScript with `apify-client`:

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/ean-13-check-digit-validator')
  .call({ codes: ['4006381333931'] });
if (run.status !== 'SUCCEEDED') throw new Error(`Run ended: ${run.status}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems({ limit: 100 });
console.log(items);
```

Python with `apify-client`:

```python
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/ean-13-check-digit-validator').call(
    run_input={'codes': ['4006381333931']})
if run['status'] != 'SUCCEEDED':
    raise RuntimeError(run['status'])
print(client.dataset(run['defaultDatasetId']).list_items(limit=100).items)
```

Use the run's returned dataset ID. A start response is run metadata, not the barcode results. Fetch further pages explicitly for exports larger than your chosen page size.

### Use with MCP

Configure an Actor-specific subset, not an unqualified growing catalog:

```bash
claude mcp add --transport http apify \
  'https://mcp.apify.com?tools=automation-lab/ean-13-check-digit-validator'
```

Claude Desktop, Cursor, and VS Code setup (use your client's HTTP MCP configuration):

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/ean-13-check-digit-validator"
    }
  }
}
```

Authenticate using your client's supported Apify authorization flow. Availability depends on Actor access and client capabilities.

Example prompts: “Validate these three EAN-13 strings and show their checksum verdicts without removing leading zeros.” Or: “Calculate the EAN-13 check digit for base 400638133393.” Discover actual names and argument schemas with read-only `tools/list`; Actor selection also adds run/data/abort helpers, not just a single tool.

For an authorized invocation, start once and keep the run ID and storage IDs. `call-actor` waits at most 45 seconds (`waitSecs` defaults to 30); if still running, check **the same run** with `get-actor-run` using bounded 2/4/8-second backoff capped at 10 seconds and a 120-second deadline. Set the client request timeout above the selected server wait plus transport margin. Recover a known run after a client timeout, never restart it just to poll. If the ID is unknown, report uncertainty. At the deadline report the pending run ID and stop polling. Terminal failures are failures; any available rows are partial.

After success, read `get-dataset-items` with explicit dataset ID, `limit`, `offset` and needed fields. A reasonable consumer budget is pages of 20 source rows, at most 100 rows or 64 KiB of UTF-8 serialized content admitted to model context, whichever comes first. Enforce byte limits host-side before model injection, including oversized single rows; otherwise do not promise a hard byte guarantee. Track source offsets, report truncation and continuation offsets, and retain full exports outside model context. These are consumer choices, not reduced Actor input limits or universal token-saving guarantees.

### Legality, privacy and responsible use

Submit only codes and data you are authorized to process. Do not paste credentials or personal customer information into barcode strings. Results include the original input strings and follow your Apify storage/access settings.

Failed operations send sanitized diagnostic input, exceptions and actor/build/run IDs to our private GlitchTip service for repair. Secret fields and URL queries are removed; reports are retained for 30 days. Avoid sensitive content in arbitrary barcode values even though telemetry is scrubbed.

This tool is not a GS1 registry service, legal certification, fraud detector or compliance approval. Verify product assignment through the appropriate authoritative source before relying on it commercially.

### FAQ and troubleshooting

**Why did my leading zero disappear?** JSON numbers and spreadsheet numeric columns lose formatting before the Actor receives them. Supply quoted strings; lost zeros cannot be reconstructed safely.

**Why is a real product marked invalid?** Check the original digit count, punctuation and copied characters. This Actor supports EAN-13 only, not EAN-8, UPC-A, GTIN-14 or ISBN-10.

**Can a fake code pass?** Yes. Checksum validity is only arithmetic consistency, not registration or authenticity.

**Does calculation repair my product code?** It returns the correct check digit for the supplied twelve digits. It cannot determine whether those twelve digits identify the intended product.

**Why are fewer rows returned?** Inspect the first-N input cap and the run's terminal status. Also check the platform billing limit. A failed or interrupted run can have partial output. Duplicate codes are not removed.

**Can it create barcode images or scan photographs?** No. It operates only on supplied digit strings.

### Related Actors

[Open Food Facts EAN UPC GTIN Lookup](https://apify.com/automation-lab/ean-upc-gtin-product-lookup) resolves food-product metadata from supplied barcodes. Use this validator for arithmetic checks and that separate Actor for product lookup; neither replaces authoritative GS1 assignment verification.

# Changelog

This Actor's version history is a separate document: https://apify.com/automation-lab/ean-13-check-digit-validator/changelog.md

# Actor input Schema

## `codes` (type: `array`):

1–10000 strings, up to 256 characters each. Keep leading zeros. Only surrounding whitespace is trimmed; internal spaces, hyphens and non-ASCII digits are invalid. Order and duplicates are preserved. Validate mode expects 13 digits; calculate mode expects 12.

## `mode` (type: `string`):

validate checks exactly 13 digits against their supplied final digit. calculate accepts exactly 12 digits and returns the completed EAN-13; isValid remains null because no check digit was supplied. One mode applies to the entire batch.

## `maxItems` (type: `integer`):

Global cap on processed input entries, including invalid codes and duplicates. Processes the first N in original order, with no deduplication. Default 20; zero is not unlimited. The platform charge budget can stop output earlier.

## Actor input object example

```json
{
  "codes": [
    "4006381333931",
    "4006381333932",
    "0123456789012"
  ],
  "mode": "validate",
  "maxItems": 20
}
```

# Actor output Schema

## `dataset` (type: `string`):

Export validation and calculation results as JSON or CSV.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "codes": [
        "4006381333931",
        "4006381333932",
        "0123456789012"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/ean-13-check-digit-validator").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "codes": [
        "4006381333931",
        "4006381333932",
        "0123456789012",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/ean-13-check-digit-validator").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "codes": [
    "4006381333931",
    "4006381333932",
    "0123456789012"
  ]
}' |
apify call automation-lab/ean-13-check-digit-validator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/ean-13-check-digit-validator"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/6cOUUFZbKpAmVL5Rq/builds/aqQyFVNGmI523Wipn/openapi.json
