Base64 Encoder Decoder Chrome Extension (2026)

Base64 encoding is a fundamental technique in web development, used for embedding binary data in text formats, handling image uploads, API authentication, and more. Having a reliable Chrome extension for Base64 encoding and decoding can significantly streamline your workflow as a developer or power user. This guide walks you through understanding, building, and using Base64 tools directly in your browser.

What Is Base64 Encoding?

Base64 is a binary-to-text encoding scheme that represents binary data in ASCII string format. It uses 64 characters (A-Z, a-z, 0-9, +, /) to represent binary data, making it safe for transmission over protocols that handle text. The encoding process converts every 3 bytes of binary data into 4 Base64 characters.

Common use cases include:

  • Embedding small images in CSS or HTML using data URIs
  • Transmitting binary data through JSON APIs
  • Encoding credentials for HTTP Basic Authentication
  • Creating compact representations of file contents for clipboard operations

Building a Chrome Extension for Base64 Operations

A Chrome extension for Base64 encoding and decoding consists of three main components: the manifest file, the popup HTML, and the JavaScript logic. Create the Manifest

The manifest.json file defines your extension’s configuration and permissions:

{
 "manifest_version": 3,
 "name": "Base64 Encoder/Decoder",
 "version": "1.0",
 "description": "Encode and decode Base64 strings quickly",
 "action": {
 "default_popup": "popup.html",
 "default_icon": "icon.png"
 },
 "permissions": ["activeTab"]
}

This minimal manifest uses Manifest V3, the current standard for Chrome extensions. The activeTab permission ensures your extension can interact with the current page when needed.

Step 2: Create the Popup Interface

The popup.html file provides the user interface:

<!DOCTYPE html>
<html>
<head>
 <style>
 body { width: 320px; padding: 16px; font-family: system-ui, sans-serif; }
 textarea { width: 100%; height: 80px; margin-bottom: 8px; }
 button { padding: 8px 16px; margin-right: 4px; cursor: pointer; }
 .result { margin-top: 12px; word-break: break-all; font-size: 12px; }
 </style>
</head>
<body>
 <h3>Base64 Tool</h3>
 <textarea id="input" placeholder="Enter text or Base64 string..."></textarea>
 <button id="encode">Encode</button>
 <button id="decode">Decode</button>
 <div class="result" id="output"></div>
 <script src="popup.js"></script>
</body>
</html>

Step 3: Implement the Logic

The popup.js file handles the encoding and decoding:

document.getElementById('encode').addEventListener('click', () => {
 const input = document.getElementById('input').value;
 try {
 const encoded = btoa(unescape(encodeURIComponent(input)));
 document.getElementById('output').textContent = encoded;
 } catch (e) {
 document.getElementById('output').textContent = 'Error: ' + e.message;
 }
});
document.getElementById('decode').addEventListener('click', () => {
 const input = document.getElementById('input').value;
 try {
 const decoded = decodeURIComponent(escape(atob(input)));
 document.getElementById('output').textContent = decoded;
 } catch (e) {
 document.getElementById('output').textContent = 'Invalid Base64 string';
 }
});

This implementation handles Unicode characters properly. The btoa() and atob() functions work directly with ASCII, so we use encodeURIComponent and escape to handle non-ASCII characters before encoding.

Advanced Features for Power Users

Beyond basic encoding and decoding, consider adding these features to make your extension more useful:

URL-Safe Base64

Standard Base64 uses + and / characters, which can cause issues in URLs. URL-safe Base64 replaces these with - and _, removing padding:

function encodeURLSafe(str) {
 return btoa(unescape(encodeURIComponent(str)))
 .replace(/\+/g, '-')
 .replace(/\//g, '_')
 .replace(/=+$/, '');
}
function decodeURLSafe(str) {
 str = str.replace(/-/g, '+').replace(/_/g, '/');
 while (str.length % 4) str += '=';
 return decodeURIComponent(escape(atob(str)));
}

File Encoding

For encoding files or larger content, you’ll need to read files and convert them to Base64:

async function encodeFile(file) {
 return new Promise((resolve, reject) => {
 const reader = new FileReader();
 reader.onload = () => resolve(reader.result.split(',')[1]);
 reader.onerror = reject;
 reader.readAsDataURL(file);
 });
}

Using Existing Base64 Extensions

If you prefer using existing tools rather than building your own, several quality Base64 extensions are available in the Chrome Web Store. When choosing an extension, look for:

  • Unicode support: Ensure it handles non-English text correctly
  • Batch processing: Ability to encode or decode multiple strings
  • Integration features: Context menu options, keyboard shortcuts
  • Privacy: Check what data the extension accesses

Common Pitfalls and Solutions

Working with Base64 in JavaScript presents several challenges:

Unicode Characters: The btoa() function only handles Latin1 characters. Always encode Unicode strings using the URI component approach shown earlier.

Large Files: Base64 increases data size by approximately 33%. For large files, consider processing in chunks or using streaming approaches.

Malformed Input: Always wrap decoding operations in try-catch blocks to handle invalid Base64 strings gracefully.

Testing Your Implementation

Verify your Base64 implementation with these test cases:

Input: "Hello, World!"
Encoded: "SGVsbG8sIFdvcmxkIQ=="
Input: ""
Encoded: "8J+QgQ=="
Input: ""
Encoded: "5rqQ5Zu+"

Adding a Copy-to-Clipboard Button

One of the most requested quality-of-life improvements for any encoding tool is instant clipboard support. Requiring users to manually select and copy the output adds friction that slows down repetitive workflows. Here is how to add a copy button to the popup:

// Add to popup.js after setting the output text
function setOutput(text) {
 const outputEl = document.getElementById('output');
 outputEl.textContent = text;
 const copyBtn = document.getElementById('copy');
 copyBtn.style.display = 'inline-block';
 copyBtn.onclick = () => {
 navigator.clipboard.writeText(text).then(() => {
 copyBtn.textContent = 'Copied!';
 setTimeout(() => { copyBtn.textContent = 'Copy'; }, 1500);
 });
 };
}

Update popup.html to include the copy button element:

<button id="copy" style="display:none;">Copy</button>

The navigator.clipboard.writeText API is available without additional permissions in Manifest V3 popup contexts because the popup has focus at the time of the call. The button resets its label after 1.5 seconds, giving users clear confirmation that the copy succeeded.

Integrating with the Current Page via Content Scripts

A standalone popup is useful, but a more powerful pattern is letting the extension detect and operate on Base64 content that already exists on the page you are viewing. This requires a content script.

Add a content script entry to manifest.json:

{
 "manifest_version": 3,
 "name": "Base64 Encoder/Decoder",
 "version": "1.0",
 "description": "Encode and decode Base64 strings quickly",
 "action": {
 "default_popup": "popup.html",
 "default_icon": "icon.png"
 },
 "permissions": ["activeTab", "scripting"],
 "content_scripts": [
 {
 "matches": ["<all_urls>"],
 "js": ["content.js"],
 "run_at": "document_idle"
 }
 ]
}

The content script can scan for strings that match the Base64 pattern and expose them for decoding on demand. A conservative pattern for detecting Base64 strings:

// content.js
const BASE64_PATTERN = /^[A-Za-z0-9+/]{20,}={0,2}$/;
function findBase64InSelection() {
 const selection = window.getSelection().toString().trim();
 if (BASE64_PATTERN.test(selection)) {
 return selection;
 }
 return null;
}
// Listen for messages from the popup
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
 if (request.action === 'getSelection') {
 sendResponse({ text: findBase64InSelection() });
 }
});

In the popup, send a message to retrieve whatever the user has selected before the popup opened:

chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
 chrome.tabs.sendMessage(tabs[0].id, { action: 'getSelection' }, (response) => {
 if (response && response.text) {
 document.getElementById('input').value = response.text;
 }
 });
});

This pattern lets users highlight a Base64 string anywhere on a page, open the extension popup, and immediately see the selected text pre-filled in the input field.

Handling JWT Tokens

JSON Web Tokens (JWTs) are one of the most common real-world uses of Base64 encoding that developers encounter. A JWT consists of three Base64url-encoded segments separated by periods: header, payload, and signature. Decoding the header and payload reveals the token’s algorithm and claims without needing to verify the signature.

Extend the extension to detect and parse JWTs automatically:

function isJWT(str) {
 const parts = str.split('.');
 return parts.length === 3 && parts.every(p => /^[A-Za-z0-9_-]+$/.test(p));
}
function decodeJWT(token) {
 const parts = token.split('.');
 const decode = (segment) => {
 // Restore padding for standard atob
 const padded = segment + '=='.slice((segment.length % 4 || 4) - 2);
 const base64 = padded.replace(/-/g, '+').replace(/_/g, '/');
 return JSON.parse(decodeURIComponent(escape(atob(base64))));
 };
 return {
 header: decode(parts[0]),
 payload: decode(parts[1]),
 signatureRaw: parts[2]
 };
}

Add detection logic in the decode button handler:

document.getElementById('decode').addEventListener('click', () => {
 const input = document.getElementById('input').value.trim();
 try {
 if (isJWT(input)) {
 const jwt = decodeJWT(input);
 const output = JSON.stringify(jwt, null, 2);
 document.getElementById('output').textContent = output;
 } else {
 const decoded = decodeURIComponent(escape(atob(input)));
 document.getElementById('output').textContent = decoded;
 }
 } catch (e) {
 document.getElementById('output').textContent = 'Invalid Base64 or JWT string';
 }
});

This makes the extension immediately useful for API debugging workflows where developers frequently need to inspect JWT claims without switching to a separate tool.

Packaging and Loading the Extension Locally

Once your extension files are ready, load them into Chrome for testing without publishing to the Chrome Web Store.

Your file structure should look like this:

base64-extension/
 manifest.json
 popup.html
 popup.js
 content.js
 icon.png

To load the extension:

  1. Open chrome://extensions in Chrome
  2. Enable “Developer mode” using the toggle in the top-right corner
  3. Click “Load unpacked”
  4. Select the base64-extension/ directory

The extension icon will appear in your toolbar immediately. Any changes you make to the source files take effect after clicking the reload button on the extension card in chrome://extensions. You do not need to re-load the entire extension for most changes.

For the icon, a simple 128x128 PNG works fine. You can generate one programmatically using a canvas element in a one-off HTML file, or use any image editing tool to create a minimal icon that distinguishes the extension in the toolbar.

Real-World Workflows Where a Base64 Extension Saves Time

Understanding where Base64 encoding actually shows up in daily development work helps you get more value from the tool you have built.

Debugging API authentication. Many APIs use HTTP Basic Authentication, which encodes a username and password as a single Base64 string in the Authorization header. When an API call fails with a 401, inspecting the raw request header and decoding the credential string immediately tells you whether the right credentials were sent. Rather than switching to a terminal and running a Python one-liner, you can paste the header value directly into the extension popup.

Inspecting image data URIs. CSS and HTML files sometimes embed small images as Base64-encoded data URIs to eliminate HTTP requests. These strings are opaque and difficult to reason about visually. Decoding and re-encoding them lets you verify that a data URI contains the image you expect, or helps you compare two versions of the same image asset during a refactor.

Working with environment variables. Some deployment platforms and CI systems store secrets as Base64-encoded environment variables to avoid issues with special characters in shell contexts. When you receive a base64 blob in a deployment log or environment config, being able to decode it instantly in the browser without context-switching to a separate tool speeds up troubleshooting significantly.

Reading serialized cookies and tokens. Session cookies and authentication tokens frequently use Base64 encoding. When you open Chrome DevTools and inspect the Application tab, cookie values often appear as opaque Base64 strings. Having the decoder a single click away in the toolbar means you can spot-check token expiry times, user IDs, or session metadata without leaving the browser.

Encoding small assets inline during prototyping. During rapid prototyping, it is sometimes faster to embed a small icon or font directly in a stylesheet as a Base64 data URI rather than setting up a separate static asset server. Your extension’s encode function handles this: drop the file into the file encoder input and paste the output directly into your CSS. This avoids the CORS and static-server configuration overhead that comes with separate asset hosting in local development.

Each of these workflows represents a case where switching to a terminal, Python, or an online tool adds a small but real context-switching cost. Keeping encoding and decoding in the browser toolbar, always one click away, compounds into meaningful time savings across a development day.

Conclusion

A Chrome extension for Base64 encoding and decoding is a valuable tool for developers working with APIs, handling data transfers, or managing binary content in text formats. Building your own gives you complete control over features and ensures you understand the underlying mechanisms. Start with the basic implementation outlined here, then expand with URL-safe variants, file support, and other features that match your specific needs.



I'm a solo developer in Vietnam. 50K Chrome extension users. $500K+ on Upwork. 5 Claude Max subscriptions running agent fleets in parallel. These are my actual CLAUDE.md templates, orchestration configs, and prompts. Not a course. Not theory. The files I copy into every project before I write a line of code. **[See what's inside →](https://zovo.one/lifetime?utm_source=ccg&utm_medium=cta-default&utm_campaign=chrome-extension-base64-encoder-decoder)** $99 once. Free forever. 47/500 founding spots left.

Related Reading

Built by theluckystrike. More at zovo.one

Find the right skill → Browse 155+ skills in our Skill Finder.