Skip to content
Parser BlogLogistics10 min readAll posts

How to Extract Data from a Bill of Lading: Fields, Cargo Lines and the Checks That Catch Bad Reads

To extract data from a bill of lading, decide which fields you need, read each bill into those fields and its cargo table into one row per line, check the result against the totals on the bill, and only then send it to your TMS or a spreadsheet. The reading is the easy part to describe and the hard part to get right: every carrier draws its own bill, and the cargo table rarely fits on one page.

In brief

  • To extract data from a bill of lading, first fix the list of fields you need, then read each B/L into those fields, validate them, and send them to your TMS or a spreadsheet.
  • A bill of lading has two parts to extract: header fields such as B/L number, parties, ports, vessel and dates, and a table of cargo lines with marks, packages, description, weight and volume.
  • The cargo lines are the hard part: descriptions wrap across lines, a table can continue on a rider page, and weights may be stated in kilograms or pounds.
  • Deterministic checks catch most bad reads: line weights and packages that add up to the totals, container numbers that pass the ISO 6346 check digit, and dates in a plausible order.

What a bill of lading actually contains

A bill of lading (B/L, or BOL in trucking) is three things at once: the carrier's receipt for the goods, the evidence of the contract of carriage and, for a negotiable ocean bill, the document of title. Whatever the mode, the data you want from it falls into two parts. The header describes the movement, and the cargo table describes what moved.

The header of an ocean bill holds the B/L number, the shipper, the consignee and the notify party, the carrier, the vessel and voyage, the place of receipt, the ports of loading and discharge, the place of delivery, the freight terms (prepaid or collect), the number of originals issued, the place and date of issue and the shipped on board date. A house bill from a forwarder carries the same fields plus a reference to the master bill the carrier issued.

The cargo table holds, for each container or group of packages, the container and seal numbers, the marks and numbers, the package count and type, the description of goods, the gross weight and the volume. A domestic truck bill of lading is shorter on ports and vessels, but adds the PRO number, the carrier SCAC, handling units, the freight class and NMFC item, and a flag for hazardous materials.

2

parts to extract from every bill: the header and the cargo table

4

checks run on the example extraction below, none of them needing judgment

11

characters in an ISO 6346 container number, the last one a check digit

Why bill of lading data entry goes wrong

Most shipping desks still retype bills into the TMS or a spreadsheet. It works at low volume and breaks quietly as volume grows, because the errors are small and look plausible.

Every carrier has its own layout

Carriers, NVOCCs and forwarders each print their own form. The B/L number sits top right on one and in a box at the bottom on the next. Parties are free-text address blocks, so the consignee's name, street and tax reference run together, and "to order of" bills put a bank or the word "order" where a company name would be.

The cargo table spills over

A consolidated shipment can list dozens of lines. When they do not fit, the bill says "see attached list" or "as per rider" and continues on extra pages, often with different column widths. Descriptions wrap across two or three lines, and the "said to contain" wording and the marks share the same column. The lines that sit on page three are the ones most often missed.

Units and numbers drift

Weights appear in kilograms on one bill and pounds on the next, sometimes both on the same bill. Volume is in cubic meters or cubic feet. A container number is eleven characters, and one transposed digit sends a tracking request for a box that is not yours.

Illustrative
Illustrative share of B/L data entry errors by field, for a desk retyping ocean bills by hand. Numbers are examples, not measured results.

Step 1: decide the fields before you read a single bill

Start from what the downstream system needs, not from what the bill happens to print. If the TMS books a shipment from the B/L number, parties, ports, vessel and container list, those are your fields. If finance also matches carrier invoices to the bill, add the freight terms and any charges the bill shows. Write each field down with a name, a type and a unit: gross_weight_kg is a number in kilograms, not a string that may say "21,160 LBS".

Model the cargo table as a list of lines, not as one long text field. Each line gets its own container, seal, marks, packages, package type, description, gross weight and volume. That one decision is what later lets you add the lines up, compare them with a packing list, or load them into a spreadsheet one row per line. The guide to designing extraction schemas covers how to type fields, model tables and version the schema when a new field is needed.

Keep header names consistent with the other documents in the same shipment. If the packing list extraction calls it gross_weight_kg, the bill of lading should too: a cross-check between documents is then a comparison of two fields with one name.

Step 2: read each bill into those fields

There are three ways to fill the fields. Manual entry needs no setup and does not scale. Fixed zone templates, which read a field from the same spot on the page each time, work for one carrier's form and must be built again for every other one and every time a carrier redesigns its bill. Model based extraction reads the bill the way a person does, by meaning rather than position, and fills the schema whatever the layout.

Whichever you use, read the whole document, rider pages included, and keep the original next to the result so a reviewer can see where each value came from. When bills arrive bundled with an invoice, a packing list and a certificate of origin in one PDF, split and classify the batch first, so the bill of lading template only ever sees bills of lading.

ExampleUpload one bill against a B/L templatebash
curl -X POST https://api.parserai.co/documents/upload \  -H "Authorization: Bearer $PARSER_API_KEY" \  -F "file=@MBL-5521093.pdf" \  -F "entity_group_id=$BL_TEMPLATE_ID"# 202 Accepted# {"documentId": "...", "extractedDocumentId": "..."}

Step 3: normalize what came back

Raw values need a small amount of cleaning before they can be compared or loaded. Convert weights to one unit and volumes to another, keeping the original value when the bill stated both. Write dates in ISO format and keep the shipped on board date separate from the date of issue, because they answer different questions: the first is the shipment date that letters of credit and sales contracts refer to, the second only dates the paper. Strip spaces and dashes from container numbers. Map port names to the codes your TMS uses.

Examplebl-extraction.json: one master bill after normalization and checksjson
{  "bl_number": "MBL-5521093",  "bl_type": "master",  "shipper": { "name": "Example Ceramics Co.", "address": "12 Harbor Rd, Valencia, ES" },  "consignee": { "name": "Orion Ltd.", "address": "400 Commerce Ave, Savannah, GA, US" },  "notify_party": { "name": "Same as consignee" },  "carrier": "Sample Ocean Lines",  "vessel_voyage": "MV Example Star 031W",  "port_of_loading": "Valencia, ES",  "port_of_discharge": "Savannah, US",  "shipped_on_board_date": "2026-10-02",  "date_of_issue": "2026-10-03",  "freight_terms": "Prepaid",  "cargo_lines": [    {      "container": "CSQU3054383",      "seal": "SL-449120",      "marks": "ORION 1-40",      "packages": 40,      "package_type": "pallet",      "description": "Glazed ceramic floor tiles, 60 x 60 cm",      "gross_weight_kg": 9600,      "volume_cbm": 18.4    },    {      "container": "CSQU3054383",      "seal": "SL-449120",      "marks": "ORION 41-52",      "packages": 12,      "package_type": "pallet",      "description": "Tile adhesive, 25 kg bags",      "gross_weight_kg": 8400,      "volume_cbm": 14.2    }  ],  "total_packages": 52,  "total_gross_weight_kg": 18000,  "checks": [    { "rule": "line_weights_equal_total", "sum": 18000, "total": 18000, "status": "pass" },    { "rule": "line_packages_equal_total", "sum": 52, "total": 52, "status": "pass" },    { "rule": "container_check_digit", "value": "CSQU3054383", "status": "pass" },    { "rule": "on_board_not_after_issue", "status": "pass" }  ]}

The cargo table came back as two lines in the same container, each with its own marks, packages and weight, and the checks at the end record that the lines add up to the totals printed on the bill.

Step 4: validate before anything is loaded

A bad read that reaches the TMS costs far more than one caught at extraction. Most errors on a bill of lading can be caught by rules that need no judgment, because the bill contains its own totals.

  • Lines add up. The sum of cargo line weights equals the total gross weight, and the sum of packages equals the total package count. A missing rider page fails this rule at once.
  • Container numbers are valid. Recompute the ISO 6346 check digit from the owner code, category letter and serial number. A single misread character almost always fails it.
  • Dates are in order. The shipped on board date is not after the date of issue, and neither is in the future.
  • Required fields are present. No bill leaves without a B/L number, a consignee and at least one cargo line.

Bills that pass go straight through. Bills that fail go to a person with the rule, the values it compared and the page they came from. Before you let the rules decide on their own, label a small set of real bills and measure accuracy field by field, with extra weight on the cargo lines.

The bill checks itself

A bill of lading prints its own totals. If the extracted cargo lines add up to the total weight and the total package count, the table was read completely. If they do not, you know which bill to look at before anyone books from it.

Step 5: send the data where it is used

Once validated, the data goes to the TMS through its API, into a spreadsheet with one row per cargo line and the header repeated, or as a CSV for a system that imports files. The same fields serve more than booking. The container list feeds tracking and demurrage monitoring. The parties, packages and weights are the bill's side of the cross-check against the commercial invoice and packing list, and the bill is one of the references in a freight invoice audit. Extracting it once, completely, saves reading it again for each of those.

Checklist: extracting bill of lading data

  • List the fields the TMS or spreadsheet needs, each with a name, a type and a unit.
  • Model the cargo table as a list of lines, not a single text field.
  • Use the same field names as the packing list and commercial invoice extractions.
  • Read every page, including riders and attached cargo lists.
  • Convert weights and volumes to one unit, and write dates in ISO format.
  • Check that line weights and packages add up to the totals on the bill.
  • Validate container numbers with the ISO 6346 check digit.
  • Send failures to a person with the rule, the values and the page.

Where Parser fits

Parser reads bills of lading against an extraction template you define: the header fields and a table of cargo lines, named and typed the way your TMS expects. Bills come in by upload, e-mail or the API, and the result goes out as JSON, Excel or CSV, or to your system by webhook. The bill of lading page lists the fields a typical template returns, and the logistics and freight page shows the other documents the same desk handles.

Frequently asked questions

FAQ
  • An ocean bill of lading carries the B/L number, shipper, consignee and notify party, the carrier, vessel and voyage, the ports of loading and discharge, the shipped on board date, the freight terms, and a cargo table with container and seal numbers, marks, package counts, descriptions, gross weights and volumes. A truck bill of lading adds items such as the PRO number, freight class and handling units.

  • Define the columns you need, such as B/L number, shipper, consignee, ports, vessel and one row per cargo line, then read each bill into that layout, either by hand or with a document extraction tool that returns the fields as structured data. Check that cargo line weights and packages add up to the totals on the bill before the data is used.

  • Every carrier and forwarder uses its own layout, parties are written as free-text address blocks, the cargo description wraps across lines and sometimes continues on an attached sheet, and units differ between bills. A person retyping dozens of bills a day will transpose digits in container numbers and miss lines on continuation pages.

  • Container numbers follow ISO 6346: four letters, six digits and a final check digit computed from the other ten characters. Recomputing the check digit flags almost every single-character misread, so an extracted container number that fails it should go to a person before it reaches the TMS.

More
The newest other posts

More from the blog.

Solutions
Where Parser fits

Related solutions.

  • Logistics & freight

    Bills of lading, freight invoices, rate confirmations and delivery receipts, read into shipment fields.

    Fields bol_number shipper consignee gross_weight_lb

    Logistics & freight, see industry
  • Invoice processing

    Vendor, tax ID, line items, taxes and due date from invoices and bills.

    Fields vendor tax_id line_items total

    Invoice processing, see use case

Your documents are different?

You define the fields in an extraction template. In the demo we process your documents live — no slides, no fluff.

30 minutes · no commitment