DIGIKEY_CLIENT_ID=… DIGIKEY_CLIENT_SECRET=… MOUSER_API_KEY=… python3 parts-relay.py
Electronics parts inventory and BOM manager
A private electronics parts inventory in your browser — scan Digi-Key, Mouser and LCSC bag labels with the camera, identify chips, boards, modules and code-less parts from a photo — by their markings or how they look (on your device), import orders, carts and KiCad BOMs, search by value ("10k 0603 1%"), plan builds for N boards, and get per-supplier purchase lists with price breaks; with storage locations, QR labels printed on sheets or straight to a Niimbot label printer, photos, and optional Digi-Key/Mouser/Nexar API lookups.
Added · updated 28 October 2026
Works with
- Label maker for Niimbot printers Images and retro graphicsprints the part, value and bin labels this page sends it
- KiCad BOM rollup Electronicsreads this inventory to show what a BOM has in stock
- Pick-and-place file fixer Electronicsreads the LCSC numbers kept here to fill gaps in a JLCPCB BOM
- Interactive assembly BOM Electronicsreads this inventory to show stock and bins beside each row of an assembly BOM
How to use it
Your parts, where they are, and what to buy for the next build. Everything lives in this browser (IndexedDB); nothing is uploaded.
How to use it
-
Inventory — every part with its MPN, manufacturer, description, category (Passives › Resistors…), package, parameters, quantity, location and supplier links. Tap −/+ to take one out or put one back; tap a row to edit everything: supplier part numbers (Digi-Key, Mouser, LCSC, Farnell), price history, datasheet, notes, tags, low-stock threshold and photos (kept in IndexedDB). ⛶ Full screen gives the table the whole screen (press F; Esc leaves).
-
Search understands values.
10k 0603 1%finds 10 kΩ 0603 resistors of 1 % or better;4k7,4.7kand4700Rare the same;100nand0.1uFare the same;50Vand1/4Wmean at least that rating;X7R,C0Gmatch the dielectric. Other words must appear somewhere (MPN, description, supplier number, location, tags). Alsocat:ics,loc:drawer 3,tag:smd,mfr:yageo,low. Bare numbers are words, not values: write100Rfor a 100 Ω resistor. Press/to search. -
Add & scan — Start camera and point it at the bag label. Digi-Key and Mouser labels carry a 2-D Data Matrix in the ECIA format (ANSI MH10.8.2 data identifiers:
Pcustomer/Digi-Key part number,1Pmanufacturer part number,30Psupplier part number,Qquantity,1Tlot,9D/10Ddate code,Kyour PO,1Ksales order,4Lcountry of origin,1Vmanufacturer). LCSC bags carry a QR code. The scan finds the part (by supplier number, then MPN) and adds the quantity — or sets the count, or creates a new part. Add each scan straight away makes unpacking an order fast. A USB or Bluetooth 2-D scanner works too: click the code box and scan. 1-D barcodes are read as a part number or a quantity. Decoding uses the browser’s BarcodeDetector where it reads Data Matrix (Chrome on Android and macOS) and ZXing elsewhere (loaded from jsDelivr). No bag label? 📸 Identify what’s in view (with the camera on) or 🔎 Identify a part from a photo hands the picture to Identify; so does Scan a photo… when the photo has no code in it. -
Identify — for parts without a bag label: a chip, a module, a board, or a part with no code at all (a pot, a relay, a motor). Take a photo (Camera), or open, drop or paste one; it is identified straight away (untick Identify as soon as there’s a photo to crop first). Drag a box around the markings or the part and press Identify again to narrow it down; ⟲ ⟳ turn the photo. It reads the markings and lists what they could be, best first, each with why ("Marking “ATMEGA328P-PU” matches ATMEGA328P with a suffix, read at 82 %"), how sure, a datasheet link and searches (Octopart, AllDatasheet, eBay, the web, Digi-Key, Mouser, LCSC). Pick one: Add to inventory records it with the quantity, location, datasheet, a note of what was read, the tag
identified, and both photos (the box and the whole picture), then opens it to check. A part you already have is recognised too: add to its stock, or just its photo.-
The markings are read by Tesseract (WebAssembly, through Tesseract.js) on a grey, contrast-stretched copy of the box, both as printed and inverted (laser marking is light on dark), and — with every angle ticked — turned 90°, 180° and 270°, stopping as soon as one reading is a sure match.
-
They are matched against a built-in list of about 160 parts that turn up on hobby boards (microcontrollers, USB-serial chips, regulators, op-amps, logic, motor drivers, sensors, RTCs, common transistors and diodes, Arduino, ESP32/ESP8266, Raspberry Pi and STM32 boards, and the usual modules) and against your inventory. Look-alike characters (O/0, I/1, S/5, B/8, Z/2, G/6) are allowed for, split words are joined (
ATMEGA 328P), suffixes and prefixes (-PU,N,SN74…) are fine, and date and lot codes are skipped. A few tiny parts print a code instead of their number (BOGIis an ADS1115); for small SOT-23 codes use SMD marking codes. -
Anything else that looks like a part number is offered as unknown, with the searches. With a Digi-Key or Mouser API key set up, the best unknown number is looked up at the suppliers straight away (and Look up with suppliers asks for any other).
-
Recognise it by how it looks uses OpenAI’s CLIP (the same model as Identify plants, birds and insects) in two steps: first which of about 45 kinds of part it is (a potentiometer, a tactile switch, a relay, a stepper motor, a servo, a screw terminal, a breadboard…), then — only if it looks like a board or module — which of the boards and modules in the list. By default it runs when the markings don’t settle it, asking once before the first download; Always runs it every time, Never not at all. A kind of part is recorded with that description and category, to fill in. On its own a look is never more than "likely".
-
Not right? Correct the markings in the text box (it re-matches as you type), search the built-in list, or add a new part by hand.
-
-
Import — drop an export: a Digi-Key order or cart (CSV or XLSX), a Mouser order or cart, an LCSC order, a KiCad BOM, or any spreadsheet with a header row. The columns are recognised from their headers; check or change each one, then add the parts to stock (or only record prices and part numbers), or turn a BOM into a project.
-
Projects & BOMs — a KiCad BOM (
kicad-cli sch export bom, or the eeschema bom_csv_grouped_by_value plugin) becomes a project. Each line is matched to your stock by a chosen part, a supplier part number, the MPN, or — for resistors, capacitors and inductors — by value and package from the designator, value and footprint (R3,4k7,R_0603_1608Metric), honouring any tolerance, voltage or dielectric the value field gives. Several matches: pick one. Set the number of boards, attrition (%, rounded up per line) and spares per line to see need / have / buy. Reserve stock holds the parts for this build so other projects don’t count them; Build takes them out of stock. -
Purchase list — the shortfall, per supplier (your preferred order, set in Data & APIs), priced from price breaks: at least the minimum order, and up to the next break when that costs no more (40 at $0.025 = $1.00, but 100 at $0.0084 = $0.84). Download each supplier’s BOM-upload CSV (Digi-Key BOM Manager, Mouser BOM tool, LCSC BOM tool) or copy Digi-Key Quick Add lines.
-
Locations & labels — cabinets › drawers › bins, as deep as you like, and labels for them and for the parts in them. The labels are drawn with the Label maker's layout, so text is sized to fit, wraps, and is cut with … only when nothing smaller fits. Pick a design:
-
Part — a QR code, the part number, its value or maker, and the description. The QR code opens the part’s datasheet (a public link, so any phone can read it) or, without one, the part here (
#part=<id>); The QR code opens switches every part label to the second. -
Bin or drawer — for a storage location: its name big, what’s in it in a few words (10k–100k 0603 resistors, 100nF 0603 capacitor; anything else by part number, the first three and +2 more, counting the locations inside it), the level above, and a QR code that opens the location here (
#loc=<id>). -
Value only — for reels, strips and cut tape: the value as large as the label allows, with the package and tolerance under it (and voltage and dielectric for capacitors).
-
-
What to label — bin labels are for the locations you tick (Tick all for every one, Tick bins for the innermost). Part and value labels are for the parts chosen in the inventory — 🏷 Labels above the list takes every part it shows, a part’s 🏷 Label just that one — or for everything in the ticked locations, in value order. It’s all one job: step through the labels with ‹ ›, and Print sends them together. Open in Label maker hands the same labels to the Label maker as rows (through this browser’s storage, not the link), to change the template, font or border there. QR codes hold only an opaque id after the
#(never sent to a server), which this browser turns into the bin or part. Someone else scanning the label learns nothing. -
Label stock — a sheet (Avery L7651, L7160, 5160, 5167, or a 62 × 29 mm roll in a label printer with a system driver; print at 100 %, or Save as PDF), or a Niimbot label printer, printed straight to: Connect by Bluetooth (or by USB). The printer, the roll and printing work exactly as in the Label maker, and share its memory in this browser: the model is read (D11, D110, D101, H1S, B1, B21, B3S, B21 Pro, M2 and the rest; choose yours before connecting to preview at its resolution), and so is the roll — from the printer when it reports the size, otherwise from NIIMBOT’s lookup of the roll’s tag (untick Look up rolls on NIIMBOT to stop it), otherwise the size you choose, remembered for that kind of roll. What the printer said shows the raw answer. The preview is the label dot for dot; set the darkness and copies, then Print.
-
Data & APIs — download a backup (JSON, optionally with photos) and import it here or elsewhere: Merge adds what is new and keeps the newer copy of anything edited in both places; Replace swaps everything. Export the inventory or stock history as CSV. Settings: currency, default low-stock level, attrition, supplier order.
What Identify downloads
Nothing until you press Identify, then once (the browser caches it), from the jsDelivr CDN: Tesseract.js and its WebAssembly engine (about 5 MB) and the English trained data (a few MB). The built-in parts list comes from this site. The first time it recognises a part by how it looks (after you say yes), it downloads transformers.js and the ONNX runtime (about 23 MB) and CLIP with 4-bit weights (about 126 MB, from the Hugging Face hub) — 4-bit rather than 8-bit because the 8-bit model mistook a potentiometer for an ST-Link, and the 4-bit one doesn’t. It runs on the GPU where WebGPU can, and on the CPU otherwise. Photos are never uploaded; the datasheet and search links are ordinary links, fetched only when you click. Datasheet links in the list were checked on 21 October 2026; parts whose maker’s site refused an automated check have searches instead.
Printing to a Niimbot loads niimbluelib (from the NiimBlue project, MIT licence, about 120 KB) from jsDelivr the first time, and talks to the printer over Web Bluetooth or Web Serial. When the printer reads only the roll’s tag, its barcode (nothing else) is sent to print.niimbot.com to look up the roll’s size, once per kind of roll — the lookup NIIMBOT’s own app makes; untick Look up rolls on NIIMBOT to stop it.
Supplier APIs (optional)
With your own keys the tool fills in descriptions, parameters, datasheets, images, price breaks and stock, when you scan a new part, look up a number, or refresh a purchase list. Responses are cached in IndexedDB for a week, and calls are spaced to stay inside each API’s limits (Digi-Key 120 a minute and 1000 a day; Mouser 30 a minute and 1000 a day).
Secrets are kept in memory and forgotten when you close the page. Remember the keys on this device stores them unencrypted in this browser’s local storage — convenient, but readable by anything that can run in this browser profile. They are never put in links or backups.
- Digi-Key
-
-
Sign in at developer.digikey.com and create an organization.
-
In it, Create production app; tick the ProductInformation V4 API. The OAuth callback is not used here (the tool signs in with the client credentials flow), so
https://localhostis fine. -
Copy the Client ID and Client Secret into Data & APIs → Digi-Key, set the locale site and currency (US/USD, UK/GBP, DE/EUR…), and press Test Digi-Key.
-
- Mouser
-
-
Sign in at mouser.com, open My Mouser → APIs (API Hub) and request a Search API key.
-
Paste it into Data & APIs → Mouser and press Test Mouser.
-
- Nexar (Octopart)
-
-
Create an app at portal.nexar.com with the Supply scope.
-
Paste its client ID and secret. Nexar returns offers from many distributors at once; its free tier has a small monthly part limit.
-
Browsers can call all three directly: checked with curl on 15 October 2026, api.digikey.com,
api.mouser.com, identity.nexar.com and api.nexar.com answer the CORS preflight and the real
request with Access-Control-Allow-Origin for this site. None of them answers product queries
without credentials (Nexar’s GraphQL endpoint answers an anonymous __typename, nothing more).
With the gitwebsite app
The gitwebsite app can hold your Digi-Key, Mouser and Nexar keys itself, in the macOS Keychain (its
Companion page, or gw companion secret set digikey|mouser|nexar). When it is running, press ⚡ Use
keys stored in the gitwebsite app under Data & APIs (approve the code in the app — in the app’s own
preview it connects by itself). Lookups for every supplier whose keys the app holds then go through
it, signed there; the page shows 🔑 Keys stored in the gitwebsite app, hides that supplier’s key
fields, and never sends or stores a key. The app only reports whether each key is present, never its
value.
The local relay
Not needed if the gitwebsite app is running — otherwise: you don’t need it either, but run it if you would rather your keys never sit in the browser, or if a network or an embedded web view blocks the direct calls.
-
Download parts-relay.py (Python 3, standard library only).
-
Start it, giving it your keys in the environment (or a
chmod 600JSON file with--secrets): -
In Data & APIs, tick Route through the relay at
http://127.0.0.1:8098, then Check relay: it lists which keys it holds (never the keys). Leave the key fields in the page empty for those.
The relay listens on 127.0.0.1 only; answers only pages from this site and local previews
(http://127.0.0.1:*, http://localhost:*, plus any --allow-origin); refuses other Host
headers (DNS rebinding); reaches only api.digikey.com, api.mouser.com, api.nexar.com and
identity.nexar.com — it is not an open proxy; forwards only the headers those APIs need (never
cookies); limits bodies to 64 KB; and signs requests itself when it holds the keys.
File formats
Header names recognised (synthetic test files use exactly these; vendors rename columns now and then, which the column mapping handles):
-
Digi-Key cart / myLists export:
Index, Quantity, Part Number, Manufacturer Part Number, Description, Customer Reference, Available, Backorder, Unit Price, Extended Price; order details export:DigiKey Part #, Manufacturer Part Number, Manufacturer, Description, Customer Reference, Quantity Ordered, Quantity Shipped, Unit Price, Extended Price. CSV or XLSX. -
Mouser order history / cart:
Mouser #, Mfr. #, Manufacturer, Customer #, Description, Order Qty., Price (USD), Ext.: (USD)(andMouser No,Mfr. No,Quantity,Unit Price (USD)). -
LCSC order:
LCSC Part Number, Manufacture Part Number, Manufacturer, Customer NO., Package, Description, RoHS, Order Qty., Min\Mult Order Qty., Unit Price($), Order Price($). -
KiCad:
kicad-cli sch export bom(defaultRefs, Value, Footprint, Qty, DNP, plus any fields such asMPN,Manufacturer,Digikey,Mouser,LCSC), and the legacy plugin’sRef, Qnty, Value, Cmp name, Footprint, Description, Vendorafter itsSource:/Date:/Tool:lines. Designator ranges likeR1-R4are expanded. -
Purchase lists: Digi-Key
Quantity, Digi-Key Part Number, Manufacturer Part Number, Manufacturer, Customer Reference, Reference Designator; MouserMouser Part Number, Manufacturer Part Number, Manufacturer, Quantity, Customer Part Number, Description; LCSCQuantity, LCSC Part Number, Manufacture Part Number, Manufacturer, Customer NO., Comment.
Limits
-
The data is in this browser only. Another browser, device, or the gitwebsite desktop app’s preview is a separate store: move it with a backup. Safari may clear site data after 7 days without a visit; download backups.
-
Identify is a good hint, not a verdict. Small or worn markings, glare on glossy packages and logos read poorly — crop tight, light from the side, and check the candidate against the datasheet. The built-in list is small; most parts will come back as an unknown number to look up. Recognising by look is a small model: in tests it named a potentiometer and a stepper motor, but took a row of tactile switches for a transistor. Fill the frame with one part on a plain background.
-
Bag-label layouts are the ECIA EIGP 114 format as Digi-Key, Mouser and LCSC print it today; other distributors' labels may put numbers in other fields (all fields are shown). Mouser labels carry no Mouser part number, so a Mouser scan matches by MPN. Glossy or wrinkled bags may need a photo instead of the live camera.
-
Parameters are read from descriptions and spec tables with simple rules — check them when it matters. Matching by value assumes the package from the footprint name.
-
Prices are what your last lookup or order said, in that supplier’s currency; there is no currency conversion, shipping, tax or tariff in the estimate. Price breaks and MOQs change; the supplier’s cart is the truth.
-
Old
.xlsfiles are not read (save as.xlsxor CSV). -
Niimbot printing needs Web Bluetooth or Web Serial: Chrome or Edge on a computer, or Chrome on Android. Safari, Firefox and every browser on iPhone and iPad can’t reach the printer — print a sheet there instead. NiimBlue’s library is a reverse-engineered protocol, not Niimbot’s own; it was tested here with its real image encoder and a simulated printer, so a model it doesn’t know yet prints with D110 (small) or B1 (wide) settings.
-
The supplier API clients were tested against recorded responses shaped from the vendors' published schemas, not live keys.
Related: Resistor colour codes and markings, Capacitors, SMD packages and footprints, Connectors, QR codes and barcodes, Work log and tasks, KiCad BOM rollup (rolls a schematic up for N boards against this stock and prices it at Digi-Key).
Linking to an example
A link can carry the inventory search (never the inventory — that stays in each visitor’s own
browser). Add a tab after #: inventory, add, identify, import, projects, locations or data.
| Parameter | Meaning | Example |
|---|---|---|
|
The search box |
|
|
Sort by |
|
|
|
|
|
A preset: |
|
In a URL % is written %25 and a space +. Label links (#loc=…, #part=…) are made by the
label printer and only mean something in the browser that holds the inventory.
Feedback is a gift. Something to improve, a feature to add, or a bug? Tell me.
Runs entirely in your browser; nothing you type leaves this page.