How to Scan Barcodes in Jupyter Notebook Using Python and OpenCV
Jupyter Notebook is a web-based interactive computing environment that lets you combine live code, equations, visualizations, and narrative text in a single document. If you have Anaconda installed, Jupyter Notebook is included by default. This tutorial walks you through building a Python barcode scanner inside a Jupyter Notebook — upload an image, decode every barcode in it, and display the annotated results inline.
What you’ll build: An interactive Jupyter Notebook that accepts image uploads via a widget button, scans all barcodes and QR codes using Dynamsoft Barcode Reader and OpenCV, and renders annotated results side-by-side with Matplotlib.
Key Takeaways
- Dynamsoft Barcode Reader’s Python SDK can decode 1D/2D barcodes from image files inside a Jupyter Notebook in a single API call via
CaptureVisionRouter. - The
ipywidgets.FileUploadwidget provides a zero-JavaScript way to accept image uploads directly in a notebook cell. - OpenCV handles image decoding and barcode-location overlay drawing, while Matplotlib renders the before/after comparison inline.
- This approach works in both classic Jupyter Notebook and JupyterLab with no extra frontend extensions required.
Common Developer Questions
- How do I scan barcodes from an uploaded image in Jupyter Notebook using Python?
- What Python library can decode QR codes and 1D barcodes inside a Jupyter Notebook cell?
- How do I display barcode detection results with bounding boxes in Jupyter Notebook?
Prerequisites
- Get a 30-day free trial license for Dynamsoft Barcode Reader.
Build a Barcode Scanner in Jupyter Notebook
-
Run Jupyter notebook:

-
Open
http://localhost:8888/in your browser to create abarcode_scanning.ipynbfile.
-
Insert a new cell to install Dynamsoft Barcode Reader, OpenCV, and Matplotlib:
%pip install dynamsoft-barcode-reader-bundle opencv-python matplotlib -
Initialize the license of barcode SDK and barcode reader object:
from dynamsoft_capture_vision_bundle import * license_key = "LICENSE-KEY" error_code, error_message = LicenseManager.init_license(license_key) cvr_instance = CaptureVisionRouter() -
Create an image upload button in Jupyter notebook:
from ipywidgets import FileUpload def on_upload_change(change): if change.name != "value": return if not change.new: return up = change.owner files_obj = change.new records = list(_flatten_records(files_obj)) for rec in records: try: content = _get_bytes(rec) except Exception as e: print("Skip unsupported record:", e) continue buf = np.frombuffer(content, dtype=np.uint8) img = cv.imdecode(buf, cv.IMREAD_COLOR) if img is None: print("Failed to decode image.") continue new_img = img.copy() try: decode(new_img) except Exception as e: print("Decode error:", e) img_rgb = cv.cvtColor(img, cv.COLOR_BGR2RGB) new_rgb = cv.cvtColor(new_img, cv.COLOR_BGR2RGB) show_image(img_rgb, new_rgb) try: up.unobserve(on_upload_change, names="value") except Exception: pass reset_done = False for val in ((), [], None): try: up.value = val reset_done = True break except Exception: continue if not reset_done: try: up.value.clear() reset_done = True except Exception: pass try: up.observe(on_upload_change, names="value") except Exception: pass uploader = FileUpload(accept='image/*', multiple=True) uploader.observe(on_upload_change, names="value") uploader -
Convert the image data to numpy array and then decode the image with OpenCV API:
import cv2 as cv import numpy as np for rec in records: try: content = _get_bytes(rec) except Exception as e: print("Skip unsupported record:", e) continue buf = np.frombuffer(content, dtype=np.uint8) img = cv.imdecode(buf, cv.IMREAD_COLOR) -
Scan barcodes with Dynamsoft Barcode Reader API:
def decode(frame): before = time.time() result = cvr_instance.capture(frame, EnumPresetTemplate.PT_READ_BARCODES.value) after = time.time() COLOR_RED = (0, 0, 255) thickness = 2 text_x, text_y = 10, 20 if result.get_error_code() != EnumErrorCode.EC_OK: print("Error:", result.get_error_code(), result.get_error_string()) cv.putText(frame, f'{after - before:.2f} s, barcode found: 0', (text_x, text_y), cv.FONT_HERSHEY_SIMPLEX, 0.5, COLOR_RED) return items = result.get_items() found = len(items) for item in items: format_type = item.get_format() text = item.get_text() print(f'Format: {format_type}, Text: {text}') loc = item.get_location() pts = np.array([[p.x, p.y] for p in loc.points], dtype=np.int32) cv.drawContours(image=frame, contours=[pts], contourIdx=-1, color=COLOR_RED, thickness=thickness, lineType=cv.LINE_AA) cv.putText(frame, f'{format_type}', (pts[0][0], pts[0][1] - 10), cv.FONT_HERSHEY_SIMPLEX, 0.5, COLOR_RED) cv.putText(frame, f'{text}', (pts[0][0], pts[0][1] - 30), cv.FONT_HERSHEY_SIMPLEX, 0.5, COLOR_RED) cv.putText(frame, f'{after - before:.2f} s, barcode found: {found}', (text_x, text_y), cv.FONT_HERSHEY_SIMPLEX, 0.5, COLOR_RED) new_img = img.copy() decode(new_img) -
Display the barcode recognition results with Matplotlib:
import matplotlib.pyplot as plt def show_image(img1, img2): fig = plt.figure(figsize=(18, 8)) ax1 = fig.add_subplot(1, 2, 1) ax1.set_title('Input image', fontsize=14) ax1.axis('off') ax2 = fig.add_subplot(1, 2, 2) ax2.set_title('Barcode Recognition', fontsize=14) ax2.axis('off') ax1.imshow(img1) ax2.imshow(img2) plt.show()
Common Issues and Edge Cases
- “License has expired” or “License invalid” error: Ensure you have replaced
"LICENSE-KEY"with a valid trial or purchased license key. Trial keys expire after 30 days — request a new one from the Dynamsoft License Portal. FileUploadwidget does not appear: Theipywidgetspackage must be installed and the Jupyter Notebook extension enabled. Run%pip install ipywidgetsand restart the kernel. In JupyterLab, you may also needjupyter labextension install @jupyter-widgets/jupyterlab-manager.cv.imdecodereturnsNone: This typically means the uploaded file is not a valid image or is corrupted. Verify the file format (JPEG, PNG, BMP are supported) and ensure the file is not zero-length.
Source Code
https://github.com/yushulx/python-barcode-qrcode-sdk/tree/main/examples/official/jupyter_notebook