A barcode or QR Code generator can be incredibly useful for quickly sharing links, managing inventory, or encoding information. In this tutorial, we'll walk you through building a Chrome extension that generates both 1D and 2D barcodes from the current webpage URL or user-inputted text.
Demo Video: 1D/2D Barcode Generator for Chrome
Chrome Extension Installation
What We're Building
A Chrome extension that can:
- Generate QR codes from any webpage with one click
- Support mainstream barcode types (QR Code, EAN13, CODE128, PDF417, etc.)
- Allow manual text input for custom barcodes
- Download barcodes as PNG images
- Copy barcodes to clipboard
- Work completely offline with no data collection
Prerequisites
- bwip-js library for barcode generation
Step 1: Project Setup
Create a new directory for your extension:
mkdir barcode-generator-extension
cd barcode-generator-extension
Create the following file structure:
barcode-generator-extension/
├── manifest.json
├── popup.html
├── popup.css
├── popup.js
├── bwip-js.min.js
└── icons/
├── icon16.png
├── icon48.png
└── icon128.png
Step 2: Create the Manifest File
The manifest.json is the heart of any Chrome extension. It defines metadata, permissions, and entry points.
Create manifest.json:
{
"manifest_version": 3,
"name": "Barcode & QR Code Generator",
"version": "1.0",
"description": "Generate 1D/2D barcodes from current page URL or custom text",
"permissions": [
"activeTab"
],
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
},
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
}
Key Points:
-
manifest_version: 3- Uses the latest Manifest V3 specification -
activeTabpermission - Only accesses the current tab when user clicks the extension -
action.default_popup- Defines the popup HTML file
Step 3: Build the User Interface
Create popup.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="popup.css">
<title>Barcode Generator</title>
</head>
<body>
<div class="container">
<h1>Barcode Generator</h1>
<div class="input-section">
<div class="button-group">
<button id="useUrl" class="btn btn-primary">Use Current URL</button>
<button id="useManual" class="btn btn-secondary">Manual Input</button>
</div>
<div class="input-group">
<label for="text">Text:</label>
<input type="text" id="text" placeholder="Enter text or click 'Use Current URL'">
</div>
<div class="input-group">
<label for="barcodeType">Barcode Type:</label>
<select id="barcodeType">
<option value="qrcode">QR Code</option>
<option value="dotcode">Dotcode</option>
<option value="pdf417">PDF417</option>
<option value="maxicode">MaxiCode</option>
<option value="azteccode">AztecCode</option>
<option value="datamatrix">DataMatrix</option>
<option value="ean13">EAN13</option>
<option value="code128">CODE128</option>
<option value="code39">CODE39</option>
<option value="interleaved2of5">ITF</option>
<option value="msi">MSI</option>
<option value="pharmacode">Pharmacode</option>
<option value="rationalizedCodabar">Codabar</option>
</select>
</div>
<button id="generate" class="btn btn-generate">Generate Barcode</button>
</div>
<div id="result" class="result-section" style="display: none;">
<canvas id="barcodeCanvas"></canvas>
<div class="action-buttons">
<button id="download" class="btn btn-success">Download</button>
<button id="copy" class="btn btn-info">Copy to Clipboard</button>
</div>
</div>
<div id="error" class="error-message" style="display: none;"></div>
</div>
<script src="bwip-js.min.js"></script>
<script src="popup.js"></script>
</body>
</html>
Step 4: Style the Extension
Create popup.css:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
width: 400px;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f5f5f5;
}
.container {
padding: 20px;
}
h1 {
font-size: 20px;
color: #333;
margin-bottom: 20px;
text-align: center;
}
.input-section {
background: white;
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
margin-bottom: 15px;
}
.button-group {
display: flex;
gap: 10px;
margin-bottom: 15px;
}
.input-group {
margin-bottom: 15px;
}
.input-group label {
display: block;
margin-bottom: 5px;
font-size: 14px;
color: #555;
font-weight: 500;
}
.input-group input,
.input-group select {
width: 100%;
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
transition: border-color 0.3s;
}
.input-group input:focus,
.input-group select:focus {
outline: none;
border-color: #007BFF;
}
.btn {
padding: 10px 15px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
font-weight: 500;
transition: all 0.3s;
}
.btn:hover {
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}
.btn-primary {
background-color: #007BFF;
color: white;
flex: 1;
}
.btn-secondary {
background-color: #6c757d;
color: white;
flex: 1;
}
.btn-generate {
width: 100%;
background-color: #28a745;
color: white;
padding: 12px;
font-size: 16px;
}
.btn-success {
background-color: #17a2b8;
color: white;
flex: 1;
}
.btn-info {
background-color: #ffc107;
color: #333;
flex: 1;
}
.result-section {
background: white;
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
text-align: center;
}
#barcodeCanvas {
max-width: 100%;
height: auto;
margin-bottom: 15px;
}
.action-buttons {
display: flex;
gap: 10px;
}
.error-message {
background: #f8d7da;
color: #721c24;
padding: 12px;
border-radius: 5px;
border: 1px solid #f5c6cb;
font-size: 14px;
text-align: center;
}
Step 5: Implement the Core Functionality
Create popup.js:
// Helper functions
function getDefaultValue(barcodeType) {
if (barcodeType === 'pharmacode') {
return '12345';
} else if (barcodeType === 'rationalizedCodabar') {
return 'A1234567890B';
} else {
return '123456789012';
}
}
function showError(message) {
const errorDiv = document.getElementById('error');
errorDiv.textContent = message;
errorDiv.style.display = 'block';
setTimeout(() => {
errorDiv.style.display = 'none';
}, 3000);
}
function showSuccess(message) {
const resultDiv = document.getElementById('result');
let successMsg = resultDiv.querySelector('.success-message');
if (!successMsg) {
successMsg = document.createElement('div');
successMsg.className = 'success-message';
successMsg.style.cssText = 'background: #d4edda; color: #155724; padding: 10px; border-radius: 5px; margin-top: 10px;';
resultDiv.appendChild(successMsg);
}
successMsg.textContent = message;
successMsg.style.display = 'block';
setTimeout(() => {
successMsg.style.display = 'none';
}, 2000);
}
// Generate barcode
function generateBarcode() {
const text = document.getElementById('text').value.trim();
const barcodeType = document.getElementById('barcodeType').value;
const canvas = document.getElementById('barcodeCanvas');
const resultDiv = document.getElementById('result');
if (!text) {
showError('Please enter text or click "Use Current URL"');
return;
}
try {
bwipjs.toCanvas(canvas, {
bcid: barcodeType,
text: text,
scale: 3,
includetext: true,
});
resultDiv.style.display = 'block';
document.getElementById('error').style.display = 'none';
} catch (error) {
showError('Error generating barcode: ' + error.message);
resultDiv.style.display = 'none';
}
}
// Download barcode
function downloadBarcode() {
const canvas = document.getElementById('barcodeCanvas');
const link = document.createElement('a');
const barcodeType = document.getElementById('barcodeType').value;
link.download = `barcode_${barcodeType}_${Date.now()}.png`;
link.href = canvas.toDataURL();
link.click();
showSuccess('Barcode downloaded!');
}
// Copy to clipboard
async function copyToClipboard() {
try {
const canvas = document.getElementById('barcodeCanvas');
const blob = await new Promise(resolve => canvas.toBlob(resolve));
await navigator.clipboard.write([
new ClipboardItem({ 'image/png': blob })
]);
showSuccess('Barcode copied to clipboard!');
} catch (error) {
showError('Failed to copy to clipboard: ' + error.message);
}
}
// Get current tab URL
async function getCurrentTabUrl() {
try {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
return tab.url;
} catch (error) {
showError('Failed to get current URL: ' + error.message);
return '';
}
}
// Event listeners
document.getElementById('useUrl').addEventListener('click', async () => {
const url = await getCurrentTabUrl();
if (url) {
document.getElementById('text').value = url;
document.getElementById('barcodeType').value = 'qrcode';
}
});
document.getElementById('useManual').addEventListener('click', () => {
document.getElementById('text').value = '';
document.getElementById('text').focus();
});
document.getElementById('generate').addEventListener('click', generateBarcode);
document.getElementById('download').addEventListener('click', downloadBarcode);
document.getElementById('copy').addEventListener('click', copyToClipboard);
document.getElementById('barcodeType').addEventListener('change', (e) => {
const currentValue = document.getElementById('text').value;
if (!currentValue || currentValue === getDefaultValue(e.target.value)) {
document.getElementById('text').value = getDefaultValue(e.target.value);
}
});
document.getElementById('text').addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
generateBarcode();
}
});
// Initialize
window.addEventListener('load', () => {
const barcodeType = document.getElementById('barcodeType').value;
document.getElementById('text').value = getDefaultValue(barcodeType);
});
Step 6: Download the Barcode Library
Note: Chrome extensions cannot use external CDN libraries due to Content Security Policy (CSP). We need to include the library locally.
Download bwip-js:
curl -o bwip-js.min.js https://cdn.jsdelivr.net/npm/bwip-js@4.1.2/dist/bwip-js-min.js
Or manually download from bwip-js GitHub releases.
Step 7: Test Your Extension Locally
- Open Chrome and navigate to
chrome://extensions/ - Enable Developer mode (toggle in top-right corner)
- Click Load unpacked
- Select your extension folder
- The extension should now appear in your toolbar
Test the features:
- Click the extension icon
- Click "Use Current URL" - it should populate the URL field
- Click "Generate Barcode" - a QR code should appear
- Try "Download" and "Copy to Clipboard" buttons
- Test different barcode types from the dropdown
Step 8: Package for Chrome Web Store
Create a ZIP file with only the essential files:
zip -r barcode-extension.zip manifest.json popup.html popup.css popup.js bwip-js.min.js README.md icons/
Step 9: Submit to Chrome Web Store
To submit your extension to the Chrome Web Store, follow these steps:
- Go to Chrome Web Store Developer Dashboard.
- Click "New Item".
- Upload your ZIP file.
- Fill in Store listing (screenshots, description, categories), Privacy, and Distribution.
- Click Submit for Review (approval is typically 1–3 business days).
Source Code
https://github.com/yushulx/barcode-qrcode-generator/tree/main/chrome-extension



Top comments (0)