For developers , No key , SVG & PNG

Free Data Matrix API

One URL returns a sharp SVG or PNG. No key, no sign-up, fair-use limits.

Build a request

Method
Text, a part number, a serial or a URL. Up to 3,116 digits; fewer letters or other characters fit.
Format

Scale: pixels per module, 1–40. Quiet zone: blank modules around the code, 1–10.

More options

Response

Example response

Symbol
14 × 14
Image
180 × 180 px
Type
image/svg+xml
Size
880 bytes

Your request as code

curl, JavaScript and Python use GET

Open it in a browser, or use it anywhere an image URL works.

https://datamatrixcodegenerator.com/api/v1/datamatrix?data=PART-000123&format=svg

  • One URL

    A GET URL works in an img tag, a spreadsheet or a browser.

  • No key, no sign-up

    Free up to 2,000 new images a day per connection.

  • GS1 DataMatrix

    gs1=1 checks check digits and dates, and adds FNC1 for you.

  • Cached and exact

    Same request, same image. Repeated GET requests come from cache and are free.

The Data Matrix Code Generator API turns one value into one Data Matrix (ECC 200) code, as an SVG or a PNG. Call it with a URL (GET) or a JSON body (POST). There is no key and nothing to install, and it uses the same encoder as the Data Matrix generator on this site. For many codes at once without code, use the bulk generator in your browser.

Quick start

The simplest call is a URL. Paste it into a browser, or use it as an image source:

https://datamatrixcodegenerator.com/api/v1/datamatrix?data=PART-000123&format=svg

HTML

An image tag is enough. The browser fetches the code; after the first request it comes from cache.

<img src="https://datamatrixcodegenerator.com/api/v1/datamatrix?data=PART-000123&amp;format=svg" alt="Data Matrix code">

In Markdown (a README, a wiki page):

![Data Matrix code for PART-000123](https://datamatrixcodegenerator.com/api/v1/datamatrix?data=PART-000123&format=svg)

curl

GET saves a PNG with 8 pixels per module:

curl -o datamatrix.png 'https://datamatrixcodegenerator.com/api/v1/datamatrix?data=PART-000123&format=png&scale=8'

POST sends the same request as JSON, which keeps the value out of the URL:

curl -X POST https://datamatrixcodegenerator.com/api/v1/datamatrix \
  -H 'Content-Type: application/json' \
  -d '{"data":"PART-000123","format":"png","scale":8}' \
  -o datamatrix.png

JavaScript (fetch)

Works in the browser (CORS is open to every origin) and in Node 18 or later. Errors come back as JSON with a code and a message.

const res = await fetch("https://datamatrixcodegenerator.com/api/v1/datamatrix", {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    "data": "PART-000123",
    "format": "svg"
  }),
});
if (!res.ok) {
  const { error } = await res.json();
  throw new Error(`${error.code}: ${error.message}`);
}
const svg = await res.text(); // image/svg+xml
document.querySelector('#code').innerHTML = svg;

Python (requests)

import requests

r = requests.post(
    "https://datamatrixcodegenerator.com/api/v1/datamatrix",
    json={"data": "PART-000123", "format": "png", "scale": 8},
    timeout=10,
)
if r.status_code != 200:
    raise SystemExit(r.json()["error"]["message"])
with open("datamatrix.png", "wb") as f:
    f.write(r.content)

Excel and Google Sheets

Put your values in column A, this formula in B2, and fill it down. Spreadsheets show PNG, not SVG, so the URL asks for format=png. The cell must be large enough to show the squares clearly.

=IMAGE("https://datamatrixcodegenerator.com/api/v1/datamatrix?format=png&scale=8&data="&ENCODEURL(A2))
  • Google Sheets and Excel for Windows (Microsoft 365) understand the formula as written.
  • Excel for Mac and Excel for the web have IMAGE() but not ENCODEURL(). If your values are only letters, digits and - . _ ~, leave it out: =IMAGE("https://datamatrixcodegenerator.com/api/v1/datamatrix?format=png&scale=8&data="&A2)
  • Excel needs a URL under 255 characters and does not follow redirects. The API answers directly, with no redirect.
  • Spreadsheet apps may fetch images through their own servers, so many sheets can share one connection's limit. Repeated values come from cache and do not count.

Values in a URL are not private

With GET, the value is part of the URL, so it is stored wherever the URL is: the spreadsheet, browser history, proxies and log files. Use POST for confidential data.

Endpoints

All endpoints are on https://datamatrixcodegenerator.com under /api/v1/, over HTTPS only.

RequestReturnsUse it for
GET /api/v1/datamatrix?data=…SVG or PNGImage tags, spreadsheets, quick tests. Cached at our edge; browsers recheck daily.
HEAD /api/v1/datamatrix?data=…Headers onlyChecking the symbol size or image size without the image.
POST /api/v1/datamatrixSVG or PNGSoftware. A JSON body keeps the value out of URLs and logs.
POST /api/v1/datamatrix/infoJSONWhat would be drawn: symbol size, codewords used, the exact bytes, GS1 fields, notices.
OPTIONS (any of the above)204CORS preflight. Browsers send it for you.

POST bodies are a JSON object with the same parameter names as the URL, sent with Content-Type: application/json. Numbers and true/false may be JSON numbers and booleans, but send data as a string, so leading zeros are kept.

Metadata: POST /info

Same parameters, no image. This is a real answer for the GS1 example below:

curl -X POST https://datamatrixcodegenerator.com/api/v1/datamatrix/info \
  -H 'Content-Type: application/json' \
  -d '{"data":"(01)09506000134352(17)271231(10)AB12","gs1":true}'
Show the JSON answer
{
  "engineVersion": "2.0.1",
  "symbol": {
    "size": "18x18",
    "rows": 18,
    "columns": 18,
    "shape": "square",
    "dmre": false,
    "dataRegions": {
      "vertical": 1,
      "horizontal": 1
    },
    "dataCodewords": 18,
    "usedCodewords": 17,
    "fill": 0.944,
    "capacity": {
      "numeric": 36,
      "alphanumeric": 25,
      "bytes": 16
    }
  },
  "data": {
    "characters": 36,
    "bytes": 30,
    "hex": "30 31 30 39 35 30 36 30 30 30 31 33 34 33 35 32 31 37 32 37 31 32 33 31 31 30 41 42 31 32",
    "charset": "ascii",
    "eci": null,
    "gs1": true
  },
  "gs1": {
    "hri": "(01)09506000134352(17)271231(10)AB12",
    "elementString": "01095060001343521727123110AB12",
    "fields": [
      {
        "ai": "01",
        "title": "Product number (GTIN)",
        "value": "09506000134352"
      },
      {
        "ai": "17",
        "title": "Expiry date",
        "value": "271231",
        "readable": "31 Dec 2027"
      },
      {
        "ai": "10",
        "title": "Batch or lot number",
        "value": "AB12"
      }
    ],
    "dictionaryRelease": "2026-01-27"
  },
  "image": {
    "format": "svg",
    "scale": 10,
    "quiet": 2,
    "widthPx": 220,
    "heightPx": 220,
    "captionAdded": false
  },
  "notices": []
}

data.hex is the exact bytes in the code (FNC1 is a symbol character, not a byte, so it is not listed). notices lists warnings such as "UTF-8 with ECI: test your scanner" or "transparent background", which the image endpoint does not report.

Parameters

Only data is required. Names are lower case. Booleans accept true/false, 1/0, yes/no. Unknown names are ignored and listed in the X-Ignored-Parameters header, so a typo is easy to spot. A parameter given twice is an error.

What to draw

Parameter Values Default What it does
data text, up to 3,116 digits (fewer for other characters) required What to encode, exactly as sent: leading zeros, spaces and case are kept. In JSON, send it as a string, not a number.
format svg | png svg SVG is vector and scales to any size. PNG is a 1-bit image with whole pixels per module.
gs1 true | false false GS1 DataMatrix. Send (AI)value pairs such as (01)09506000134352(17)271231(10)AB12. Check digits, dates and field lengths are checked; FNC1 and separators are added for you.
shape square | rectangle | dmre square rectangle uses the 6 standard ECC 200 rectangles. dmre also allows the 18 DMRE rectangles (ISO/IEC 21471), which many older scanners cannot read. Ignored when size names a size.
size auto | RxC auto Force one symbol size, rows x columns, such as 24x24 or 16x48. If the data does not fit, the error names the smallest size that does.

Image size

Parameter Values Default What it does
scale or module 1–40 10 Whole pixels per module (each small square). The image is (columns + 2 x quiet) x scale pixels wide.
width 10–4,000 px none Target image width in pixels, quiet zone included. The API picks the largest whole number of pixels per module that fits, so the image can be a little narrower. Use it instead of scale.
quiet 1–10 modules 2 Blank border (quiet zone) on every side, in whole modules. It never goes below 1 module.
module_mm SVG only 0.05–20 mm none Module size in millimeters. The SVG gets width and height in mm, so it prints at true size.
dpi PNG only 72–2,400 300 Resolution stored in the PNG (pHYs), so print and layout apps know the intended size. It does not change the pixels.

Text and look

Parameter Values Default What it does
charset auto | latin1 | utf8 | utf8-eci auto auto sends ASCII and Latin-1 as single bytes, and anything else as UTF-8 with an ECI flag. utf8 skips the flag, which some scanners prefer. Ignored in GS1 mode.
escapes true | false false Read \n \r \t \G (group separator) \R \E \xHH and \\ in data. Off: backslashes are encoded as typed. Not used in GS1 mode.
dark or color, fg hex color 000000 Color of the modules, as 3 or 6 hex digits, with or without #. It must be darker than light (no inverted codes).
light or bg, background hex color | transparent ffffff Background color. The pair must have enough contrast to scan. transparent leaves the background empty: place the code on a plain, light surface.
caption SVG only text, up to 200 characters none One line of text under the code, outside the quiet zone.
download true | false | file name false Asks the browser to save the file (Content-Disposition: attachment). A name (letters, digits, - _ .) sets the file name; the extension is added for you.

Image size: a PNG is (columns + 2 × quiet) × scale pixels wide. The default 14 × 14 code for PART-000123 at scale 10 with a 2-module quiet zone is 180 × 180 pixels. Pixels per module are always whole, so edges stay sharp; nothing is stretched or smoothed.

Responses and headers

A successful request returns 200 and the image. These headers describe it, and every one is readable from browser code (CORS exposes them):

HeaderExampleMeaning
Content-Typeimage/svg+xml; charset=utf-8 or image/pngThe format you asked for.
Cache-Controlpublic, max-age=86400, s-maxage=31536000, stale-while-revalidate=604800GET only: browsers keep it a day, then recheck with the ETag. POST answers are no-store.
ETag"2301bf754d8f438cc832c01335acd8a5"Changes only when the image would change. Send it back as If-None-Match to get 304.
X-CacheHIT or MISSGET only. HIT means our edge served a stored copy (free: it does not count).
X-Symbol-Size14x14The symbol size used, rows x columns.
X-Symbol-Rows, X-Symbol-Columns14, 14The same as two numbers.
X-Symbol-Codewords8/8Data codewords used out of those the size holds.
X-Image-Width, X-Image-Height180, 180Pixels, quiet zone included. Absent for an SVG sized in mm.
X-Engine-Version2.0.1The encoder version that drew the image.
X-Ignored-Parametersv, tNames you sent that the API does not know (a typo shows up here).
Content-Dispositioninline, or attachment; filename="…"attachment when you set download.
Content-Security-Policydefault-src 'none'; …; sandboxSVG only: an opened SVG can never run scripts or load anything.

Every response also carries Access-Control-Allow-Origin: * (no cookies or credentials), X-Content-Type-Options: nosniff and Cross-Origin-Resource-Policy: cross-origin, so the images embed on any page.

Errors

Errors return JSON with an HTTP status that matches the problem, and are never cached. code is stable and safe to branch on; message is for people; hint says what to change; param names the parameter; detail is the encoder's own reason. This is a real error, for 100 characters forced into a 10 × 10 code:

{
  "error": {
    "code": "data_not_encodable",
    "message": "This text does not fit in a 10 × 10 code. It needs at least 36 × 36.",
    "hint": "Use size=auto, or size=36x36 or larger.",
    "param": "size",
    "detail": "does-not-fit-size",
    "docs": "https://datamatrixcodegenerator.com/data-matrix-api/#errors"
  }
}

Request problems

Status Code Meaning
400 missing_data No data was sent, or it was empty.
400 invalid_parameter A parameter has the wrong type or is out of range. param names it.
400 bad_request The POST body is not a JSON object.
404 not_found There is no endpoint at that path.
405 method_not_allowed The method is not supported here. The Allow header lists the ones that are.
413 data_too_long data is longer than any symbol can hold (the largest, 144x144, takes 3,116 digits, 2,335 capital letters or 1,556 bytes).
413 payload_too_large The POST body is larger than 32 KB.
415 unsupported_media_type A POST without Content-Type: application/json.

Data problems

Status Code Meaning
422 data_not_encodable The data does not fit the size or shape you chose, uses a character the charset cannot hold, or has a bad escape. detail gives the reason.
422 gs1_invalid GS1 data failed a syntax check, such as a wrong check digit or an impossible date. detail names the check.
422 colors_not_scannable The colors are inverted (light modules on a dark background) or too close in brightness to scan.
422 image_too_large The image would be more than 4,000 pixels on a side. Lower scale or width.

Limits and server

Status Code Meaning
429 rate_limited Too many new images from one connection. Wait the number of seconds in Retry-After.
500 server_error Something failed on our side. Retry later, and tell us if it keeps happening.

The API never shortens your data to make it fit. If it does not fit, you get 422 and the smallest size that would work.

Limits and fair use

The API is free and has no key, so it has limits that keep it fast for everyone:

  • 2,000 new images a day per connection. Short bursts above about 60 a minute may also be slowed. Over the daily limit, or in a large burst, you get 429 and a Retry-After header in seconds.
  • Cached GET repeats are free. A GET our edge has already answered, or a 304 after If-None-Match, does not count. POST is never cached, so every POST counts.
  • Data: whatever fits the largest symbol (144 × 144): 3,116 digits, 2,335 capital letters or 1,556 bytes of other text.
  • Image: up to 4,000 pixels a side, 40 pixels per module. POST body: up to 32 KB.

Please store images you reuse, rather than asking for the same one again from a server, and spread large jobs out. It is a free service: there is no uptime promise, and we may change the limits or block abusive use (see the terms). For thousands of codes in one go, the bulk generator makes up to 5,000 codes per export in your browser, with no API limits.

Caching and ETags

  • Same request, same image. Output depends only on the parameters and the encoder version, so GET answers are sent with Cache-Control: public, max-age=86400, s-maxage=31536000, stale-while-revalidate=604800. Our edge keeps an image for a year; browsers, CDNs and spreadsheet apps keep it for a day, then recheck it with the ETag, which costs nothing when the image has not changed.
  • Order and case do not matter at our edge. ?data=A&format=png and ?format=PNG&data=A share one cached copy.
  • ETags. Every image has a strong ETag. Send it back in If-None-Match and you get 304 Not Modified, which costs nothing and does not count.
  • POST is never cached (no-store): keep the result yourself if you need it again.
  • Encoder updates. The cache key includes the encoder version (now 2.0.1). If we change how codes are drawn, the ETag changes too, so embedded images pick up the new drawing within about a day; images already cached stay valid codes.

Privacy

To draw a code, the API has to receive the value. It returns the image and keeps nothing: the value, caption and image are not logged or stored. Rate limits use a daily hashed connection value, never the IP address, and we keep only daily totals of requests by format and result. Details are in the privacy policy.

GET or POST? With GET the value is in the URL, so it can end up in browser history, proxy and server logs, analytics tools and anywhere the URL is pasted. That is fine for part numbers on a public page. For anything private (patient, customer or unreleased product data), use POST, which keeps the value in the request body.

GS1 DataMatrix

Add gs1=1 and send the data as (AI)value pairs, the way it prints under the code. For example, GTIN + expiry date + batch:

https://datamatrixcodegenerator.com/api/v1/datamatrix?data=(01)09506000134352(17)271231(10)AB12&format=png&gs1=1
  • The parentheses are not encoded. The code starts with FNC1, and a group separator follows each variable-length field that is not last. Scanners report ]d2.
  • Checks: GTIN and SSCC check digits, YYMMDD dates (day 00 means end of month; since 1 January 2025 regulated healthcare products must give the real day, and the notice gs1-day00-healthcare warns on medicine-style data), value lengths and characters, and pairs that GS1 requires or forbids, using the GS1 Barcode Syntax Dictionary.
  • A failed check returns 422 gs1_invalid, with the rule in detail (for example gs1-incorrect-check-digit).
  • Passing means the supported GS1 fields passed syntax checks. It does not prove that a GTIN is registered to you or that a trading partner will accept the label. We are not GS1.

To fill in GS1 fields one by one, with dates and check digits explained, use the GS1 DataMatrix generator.

Symbol sizes

Data Matrix ECC 200 has 48 sizes: 24 squares, 6 standard rectangles and 18 DMRE rectangles. With size=auto the API picks the smallest one of your shape that fits. Force one with size, written rows x columns. DMRE sizes (ISO/IEC 21471) are newer: test them with your scanners before you print.

Show all 48 sizes and their capacities
sizeShapeDigitsCapital lettersBytes
10x10Square631
12x12Square1063
14x14Square16106
16x16Square241610
18x18Square362516
20x20Square443120
22x22Square604328
24x24Square725234
26x26Square886442
32x32Square1249160
36x36Square17212784
40x40Square228169112
44x44Square288214142
48x48Square348259172
52x52Square408304202
64x64Square560418277
72x72Square736550365
80x80Square912682453
88x88Square1,152862573
96x96Square1,3921,042693
104x104Square1,6321,222813
120x120Square2,1001,5731,047
132x132Square2,6081,9541,301
144x144Square3,1162,3351,555
8x18Rectangle1063
8x32Rectangle20138
12x26Rectangle322214
8x48DMRE rectangle362516
12x36Rectangle443120
8x64DMRE rectangle483422
8x80DMRE rectangle644630
16x36Rectangle644630
8x96DMRE rectangle765536
12x64DMRE rectangle866341
20x36DMRE rectangle886442
8x120DMRE rectangle987247
16x48Rectangle987247
20x44DMRE rectangle1128254
16x64DMRE rectangle1249160
8x144DMRE rectangle1269361
12x88DMRE rectangle1289462
26x40DMRE rectangle14010368
22x48DMRE rectangle14410670
24x48DMRE rectangle16011878
20x64DMRE rectangle16812482
26x48DMRE rectangle18013388
24x64DMRE rectangle216160106
26x64DMRE rectangle236175116

Capacities are the published ISO/IEC 16022 and 21471 figures for one kind of character. Mixed text fits somewhere in between.

Versioning and terms

The version is in the path: /api/v1/. Within v1 we only add things, such as new optional parameters or headers. A change that could break your code would get a new path (/api/v2/), with v1 kept running alongside it for a transition period announced on this page. The X-Engine-Version header tells you which encoder drew an image.

Use of the API is covered by the terms of use. The codes you make are yours, with no watermark and no attribution required. A link back to this page is always appreciated.

Planned

Need higher limits or batch jobs?

An API plan with higher limits, finished batch jobs (many codes and a labels PDF from one request) and private download links is planned, from $29 a month, starting as a small pilot. It is not on sale yet. Tell us your volume and we will email you when it opens. The pricing page compares higher API limits with the free tier.

Frequently asked questions

Is the Data Matrix API free?

Yes. There is no key and no sign-up. Each connection can make up to 2,000 new images a day; short bursts above about 60 a minute may be slowed. GET requests our edge has already answered come from cache and do not count (POST is never cached). Higher limits are planned: see higher API limits.

Can I use it in Excel or Google Sheets?

Yes, with the IMAGE() function and a GET URL that asks for format=png (spreadsheets do not show SVG). Put the value in A2 and use =IMAGE("https://datamatrixcodegenerator.com/api/v1/datamatrix?format=png&data="&ENCODEURL(A2)). ENCODEURL works in Google Sheets and Excel for Windows. The value travels in the URL, so do not use this for confidential data.

Does it support GS1 DataMatrix?

Yes. Add gs1=1 and send (AI)value pairs, for example (01)09506000134352(17)271231(10)AB12. The API checks check digits, dates and field lengths against the GS1 syntax dictionary, adds FNC1 and group separators, and never encodes the parentheses. It cannot prove that a GTIN is registered to you. The GS1 DataMatrix generator explains each field.

What are the rate limits?

Up to 2,000 new images a day from one connection (we count a daily hashed IP address, never the address itself). Short bursts above about 60 a minute may also be slowed. Over the daily limit, or in a large burst, you get 429 with a Retry-After header in seconds. Cached GET repeats and 304 answers are free; POST requests always count.

Do you store the data I send?

No. The API draws the code and returns it. It does not log or store the value, the caption or the image. We keep only daily totals of requests by format and result. With GET, the value is part of the URL, so other systems on the way (your browser history, proxies, log files) may record it. Use POST for anything private.

Which sizes and shapes can it make?

All 48 ECC 200 sizes: 24 squares from 10 × 10 to 144 × 144, 6 standard rectangles and 18 DMRE rectangles (ISO/IEC 21471). By default it picks the smallest square that fits. Use shape or size to choose. See symbol sizes.

Can I get a print-ready, true-size file?

For SVG, set module_mm (for example 0.5) and the SVG gets its width and height in millimeters. For PNG, set scale to whole pixels per module and dpi to your printer resolution. For label sheets or a PDF, use the Data Matrix generator or label maker in your browser.

Do I need an SDK?

No. Any HTTP client works: an <img> tag, curl, fetch, Python requests, or a spreadsheet. CORS is open to every origin, without cookies, so browser code on any site can call it.