US Driver License PDF417 API
Decode the PDF417 barcode on the back of a US driver license or State ID and receive normalized AAMVA fields as JSON. The service uses deterministic barcode decoding and protocol parsing instead of asking a generative model to guess unreadable identity data.
Endpoint
POSThttps://api.structocr.com/v1/driver-license-pdf417Price: 2 credits for a successful decode. Processing failures are automatically refunded.
Request Parameters
Send one JPG, PNG, or WebP image using Base64 JSON or multipart form data. Keep the full barcode visible, in focus, and free from glare.
| Parameter | In | Required | Description |
|---|---|---|---|
| x-api-key | Header | Required | Your StructOCR API key. |
| Content-Type | Header | Required | application/json or multipart/form-data. |
| img / image | JSON body | JSON only | Raw Base64 or a Base64 data URI. |
| file / img | Form field | Multipart only | One image file. Maximum decoded size: 4.5 MB. |
Response Schema
Required identity fields are always present on success. Optional AAMVA fields return null when absent.
| Field | Description |
|---|---|
| type | string — Response schema type; always drivers_license for this endpoint, including State ID cards. Use document_kind to tell them apart. |
| document_kind | string — driver_license or id_card, from the AAMVA subfile type. Enhanced cards without a license class are reported as id_card. |
| source | string — Extraction source; always pdf417 for this endpoint. |
| country_code | string | null — Country code encoded in the AAMVA record, commonly USA. |
| region | string | null — Issuing US state or jurisdiction code, such as CA or NY. |
| document_number | string — Driver license or State ID number. |
| surname | string — Cardholder family name. |
| given_names | string — Combined first and middle names. |
| first_name | string | null — Cardholder first name. |
| middle_name | string | null — Cardholder middle name. |
| name_suffix | string | null — Name suffix when encoded. |
| sex | string | null — Normalized M or F when explicitly encoded. |
| date_of_birth | string — Birth date normalized to YYYY-MM-DD. |
| date_of_issue | string | null — Issue date normalized to YYYY-MM-DD. |
| date_of_expiry | string | null — Expiration date normalized to YYYY-MM-DD. |
| address | string | null — Combined street address lines. |
| city | string | null — Mailing city. |
| postal_code | string | null — Normalized postal code. |
| vehicle_class | string | null — Jurisdiction-defined license class. |
| restrictions | string | null — License restrictions encoded in the record. |
| endorsements | string | null — License endorsements encoded in the record. |
| height | string | null — Encoded cardholder height. |
| eye_color | string | null — Encoded eye color. |
| document_discriminator | string | null — AAMVA document discriminator (DCF). |
| issuer_identification_number | string — Six-digit issuer identification number from the ANSI header. |
| aamva_version | number — AAMVA version from the ANSI header. |
| jurisdiction_version | number | null — Jurisdiction version from the ANSI header; null for legacy version 01 headers that omit it. |
Code Examples
Request Implementation
curl -X POST https://api.structocr.com/v1/driver-license-pdf417 \
-H "x-api-key: YOUR_API_KEY" \
-F "file=@license-back.jpg"Success Response (200 OK)
{
"success": true,
"data": {
"type": "drivers_license",
"document_kind": "driver_license",
"source": "pdf417",
"country_code": "USA",
"region": "CA",
"document_number": "TEST123456",
"surname": "SAMPLE",
"given_names": "ALEX MORGAN",
"first_name": "ALEX",
"middle_name": "MORGAN",
"name_suffix": null,
"sex": "F",
"date_of_birth": "1990-01-15",
"date_of_issue": "2025-01-15",
"date_of_expiry": "2030-01-15",
"address": "100 EXAMPLE AVE",
"city": "SAMPLE CITY",
"postal_code": "90001",
"vehicle_class": "C",
"restrictions": "NONE",
"endorsements": "NONE",
"height": "066 IN",
"eye_color": "BRO",
"document_discriminator": "TEST-DISCRIMINATOR",
"issuer_identification_number": "636000",
"aamva_version": 10,
"jurisdiction_version": 0
}
}Live API Test
Use the request examples above with a back-side image containing a PDF417 barcode. For front-side or international license OCR, use the Driver License OCR API.
Error Responses
400 Bad Request - Invalid Input
{
"success": false,
"error": "INVALID_IMAGE",
"message": "The uploaded image could not be decoded."
}402 Payment Required - Insufficient Credits
{
"success": false,
"error": "INSUFFICIENT_CREDITS",
"message": "Your account balance is insufficient to complete this operation. Top up at https://structocr.com/dashboard/billing",
"top_up_url": "https://structocr.com/dashboard/billing"
}413 Payload Too Large
{
"success": false,
"error": "FILE_TOO_LARGE",
"message": "The image exceeds the 4.5MB limit."
}415 Unsupported Media Type
{
"success": false,
"error": "UNSUPPORTED_FILE_FORMAT",
"message": "Supported formats are JPG, PNG and WebP."
}422 Unprocessable Entity - PDF417 Not Detected
{
"success": false,
"error": "PDF417_NOT_DETECTED",
"message": "No PDF417 barcode was detected in this image. Retake the photo.\nPhotograph the barcode on the back of the license, not the whole card:\n1. Move close so the entire barcode fills most of the frame, leaving a small clear margin on all four sides. Do not crop any edges.\n2. Hold the phone steady, face the barcode straight-on, and tap on the barcode to focus until the bars look sharp.\n3. Avoid glare and shadows over the barcode.\n4. Upload the original camera photo, not a screenshot or a copy compressed by a chat app.\nIf this is the front of the license, read it with Driver License OCR instead: API /v1/driver-license, or the web tool at structocr.com/tools/driver-license-scanner.",
"capture_issue": "unknown"
}422 Unprocessable Entity - PDF417 Not Decoded (blurry barcode)
{
"success": false,
"error": "PDF417_NOT_DECODED",
"message": "The PDF417 barcode area is too blurry to read. Retake the photo focused on the barcode.\nPhotograph the barcode on the back of the license, not the whole card:\n1. Move close so the entire barcode fills most of the frame, leaving a small clear margin on all four sides. Do not crop any edges.\n2. Hold the phone steady, face the barcode straight-on, and tap on the barcode to focus until the bars look sharp.\n3. Avoid glare and shadows over the barcode.\n4. Upload the original camera photo, not a screenshot or a copy compressed by a chat app.",
"capture_issue": "out_of_focus"
}422 Unprocessable Entity - Invalid AAMVA
{
"success": false,
"error": "AAMVA_NOT_VALID",
"message": "The barcode was decoded, but its data could not be validated as a supported AAMVA driver license record."
}502 Bad Gateway - Decoder Error
{
"success": false,
"error": "PDF417_UPSTREAM_ERROR",
"message": "The PDF417 decoder could not process the request. Please try again."
}502 Bad Gateway - Invalid Decoder Response
{
"success": false,
"error": "PDF417_INVALID_RESPONSE",
"message": "The PDF417 decoder returned an invalid response. Please try again."
}503 Service Unavailable
{
"success": false,
"error": "PDF417_SERVICE_UNAVAILABLE",
"message": "The PDF417 decoder is temporarily unavailable. Please try again later."
}Status Code Definitions
| Code | Error Code | Description |
|---|---|---|
| 200 | SUCCESS | PDF417 checksum and required AAMVA identity fields were validated. |
| 400 | INVALID_JSON / NO_IMAGE_DATA / INVALID_IMAGE | The request body or decoded image is invalid. |
| 401 | AUTH_FAILED | The x-api-key header is missing. |
| 402 | INSUFFICIENT_CREDITS | The account does not have the 2 credits required to run the request. |
| 403 | INVALID_KEY / KEY_SUSPENDED | The API key is invalid, inactive, or revoked. |
| 413 | FILE_TOO_LARGE | The decoded image exceeds 4.5 MB. |
| 415 | UNSUPPORTED_FILE_FORMAT | Only JPG, PNG, and WebP images are accepted. |
| 422 | PDF417_NOT_DETECTED | No PDF417 symbol was detected in this attempt. The request is refunded. |
| 422 | PDF417_NOT_DECODED | A possible symbol was detected, but no reliable payload could be recovered. The request is refunded. |
| 422 | AAMVA_NOT_VALID | The barcode is not a usable AAMVA driver-license record. The request is refunded. |
| 502 | PDF417_UPSTREAM_ERROR | The decoder returned an upstream error. Retry with backoff. |
| 502 | PDF417_INVALID_RESPONSE | The decoder returned an invalid response. Retry with backoff. |
| 503 | PDF417_SERVICE_UNAVAILABLE | The decoder is temporarily unavailable. Retry with backoff. |
Capture Issue Hints
PDF417_NOT_DETECTED and PDF417_NOT_DECODED responses may include an optional capture_issue field. It is an advisory hint for your retake prompt, not a guarantee, and new values may be added later, so treat unrecognized values as unknown.
| capture_issue | Meaning and suggested prompt |
|---|---|
| image_too_small | The image is 500 px or smaller on its long edge. Ask the user for the original camera photo or a closer retake. |
| out_of_focus | A barcode-like area was found but is too blurry to read. Ask the user to retake the photo close to the barcode and tap on it to focus. |
| unknown | No specific cause was identified. Show the general retake guidance. |
Most failed requests are whole-card phone photos where the camera focused on the card face and the barcode came out soft. Show capture guidance in your app before the user takes the photo:
Photograph the barcode on the back of the license, not the whole card: 1. Move close so the entire barcode fills most of the frame, leaving a small clear margin on all four sides. Do not crop any edges. 2. Hold the phone steady, face the barcode straight-on, and tap on the barcode to focus until the bars look sharp. 3. Avoid glare and shadows over the barcode. 4. Upload the original camera photo, not a screenshot or a copy compressed by a chat app.