Barcodes.GG Product data & API

How to Build a Barcode Scanner Product-Lookup Feature

A scan-to-lookup feature has two halves: reading the barcode from the camera, and resolving that number to a product. This guide walks through both, plus the validation and caching layer that keeps the experience fast and reliable.

The Barcodes.GG team 4 min read

The scan-to-lookup pipeline

Every scanner feature follows the same pipeline, and building it in stages keeps each part testable.

  1. Capture: read the barcode from the camera or a hardware scanner.
  2. Clean: strip stray characters and confirm you have digits.
  3. Validate: check length and check digit before any network call.
  4. Lookup: send the GTIN to a product-data API.
  5. Render: show the result, or fall back gracefully on a miss.

Treat these as separate functions so you can unit-test validation and rendering without a live camera.

In JavaScript-flavored pseudocode the whole pipeline collapses into one readable function, where each numbered step maps to a stage above:

async function onScan(rawValue) {
  const digits = stripNonDigits(rawValue)                 // 1. clean
  if (!isValidGtin(digits)) return promptRescan()         // 2. validate locally
  const gtin = normalizeGtin(digits)                      // 3. one canonical length
  const product = cache.get(gtin) ?? await lookupViaBackend(gtin)  // 4. server-side proxy
  return product ? renderProduct(product) : renderMiss(gtin)       // 5. render or fall back
}

Capturing the barcode

On the web, the browser BarcodeDetector API decodes many symbologies natively, with mature open-source libraries as a fallback for wider device support. On mobile, native camera frameworks and cross-platform scanner libraries handle the same job.

  • Request camera permission clearly and handle denial without breaking the flow.
  • Give visual feedback the moment a code is detected, so scanning feels responsive.
  • Debounce detection so a single physical scan does not fire multiple lookups.

The output of this stage is just a string of digits. Everything after this point is identical whether the number came from a camera, a handheld scanner, or manual entry.

Warning

Client-side capture is the least reliable link in the chain. Poor light, motion blur, and damaged labels all produce misreads, and a misread that still passes as digits will sail straight to your API as a wasted request. Debounce detection so one physical scan cannot fan out into a burst of calls, validate every read locally before the network, and respect your plan rate limits by caching and queueing rather than firing a lookup on every frame.

Validate before you call the API

Cameras misread, especially in poor light, so never send raw scanner output straight to the network. Validate the GTIN first to catch bad reads locally and avoid wasted requests.

Implement the check-digit test described in how to validate a barcode, and use the barcode validation tool to verify your implementation against known-good numbers. If a read fails validation, prompt the user to scan again rather than showing a confusing not-found result.

Normalize, then look up

Different scanners and regions produce different GTIN lengths for the same product. Normalize every valid read to one canonical length before you look it up or cache it, using the GTIN converter logic. This prevents the same product from appearing under two cache keys.

Then send the normalized GTIN to your product-data API through your own backend. Keep your API key server-side and proxy the call, so the key never ships in the client. The exact request format lives in the API documentation, and you can preview a resolved result on an example page like this lookup.

Rendering results and handling misses

Design the result view around uneven data. A match may arrive with a title and brand but no image, or a category but no description, so null-check every field before rendering. For the shape of a typical response see what data a barcode lookup API returns.

  • Hit: render available fields and store the record in your cache.
  • Miss: offer manual entry or a report-this-item action.
  • Error: retry once, then show a clear, recoverable message.

The difference between a hit, a miss, and an error matters because each deserves a different recovery. A miss means the number was valid but no record exists, so the right move is manual entry or a report action. An error means the request itself failed - a timeout, a rate limit, or a transient network fault - so a single retry with backoff is appropriate before you surface anything to the user.

Collapsing all three into one generic failure state is the most common cause of a scanner feature that feels broken. Keep them distinct in your state model so the interface can guide the user toward the action that will actually resolve their situation.

Making it fast at scale

The perceived speed of a scanner feature comes from caching. Store each resolved product by its normalized GTIN and serve repeat scans locally, which matters a lot in warehouse and retail settings where the same items are scanned repeatedly.

  • Cache hits so repeat scans return instantly and reduce API calls.
  • Cache misses briefly, so items added later can still resolve.
  • Queue lookups when offline and reconcile when the connection returns.

When you are ready for production volume, compare API tiers on the plans page and follow the barcode API guide for the integration details.

Frequently asked questions

Do I need a special library to read barcodes in a browser?

Modern browsers include the BarcodeDetector API, and mature open-source libraries cover devices that lack it. Both return a plain digit string that you then validate and look up.

Should the API call happen on the device or the server?

Route it through your own server. That keeps your API key out of the client, and lets you centralize caching, rate control, and key rotation.

How do I stop one scan from firing many lookups?

Debounce detection and validate before calling. A single physical scan should produce one normalized GTIN and at most one network request.