Building a Chrome Extension with the Easy Email Finder API
Published February 19, 2026
Email Discovery Right in Your Browser
Imagine browsing Google Maps, finding an interesting business, and clicking a button to instantly see their email address. In this tutorial, you will build a Chrome extension that does exactly that, powered by the Easy Email Finder API.
Extension Architecture
Our extension has three components:
- Content script: Injects the "Find Email" button into Google Maps pages
- Background service worker: Handles API calls (keeps the API key secure)
- Popup: Settings panel for API key configuration and credit balance display
Step 1: Manifest File
Create the manifest.json file that defines your extension:
{
"manifest_version": 3,
"name": "Easy Email Finder",
"version": "1.0.0",
"description": "Find business emails from Google Maps",
"permissions": ["storage", "activeTab"],
"host_permissions": [
"https://easyemailfinder.com/*"
],
"background": {
"service_worker": "background.js"
},
"content_scripts": [{
"matches": ["https://www.google.com/maps/*"],
"js": ["content.js"],
"css": ["content.css"]
}],
"action": {
"default_popup": "popup.html",
"default_icon": "icon.png"
}
}
Step 2: Background Service Worker
The service worker handles all API communication, keeping your API key out of content scripts:
// background.js
const EEF_BASE = "https://easyemailfinder.com/api/v1";
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === "enrich") {
handleEnrich(request.website).then(sendResponse);
return true; // Keep message channel open for async response
}
if (request.action === "getBalance") {
handleGetBalance().then(sendResponse);
return true;
}
});
async function getApiKey() {
const data = await chrome.storage.sync.get("eef_api_key");
return data.eef_api_key || "";
}
async function handleEnrich(website) {
const apiKey = await getApiKey();
if (!apiKey) {
return { error: "API key not configured. Click the extension icon to set it up." };
}
try {
const resp = await fetch(`${EEF_BASE}/enrich`, {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({ website })
});
if (resp.status === 401) return { error: "Invalid API key" };
if (resp.status === 402) return { error: "No credits remaining" };
if (resp.status === 429) return { error: "Rate limited. Try again in a moment." };
return await resp.json();
} catch (err) {
return { error: "Network error. Check your connection." };
}
}
async function handleGetBalance() {
const apiKey = await getApiKey();
if (!apiKey) return { credits: 0 };
try {
const resp = await fetch(`${EEF_BASE}/balance`, {
headers: { "Authorization": `Bearer ${apiKey}` }
});
return await resp.json();
} catch {
return { credits: 0 };
}
}
Step 3: Content Script
The content script detects when you are viewing a business on Google Maps and injects the "Find Email" button:
// content.js
function injectEmailButton() {
// Check if we already injected
if (document.querySelector('.eef-email-btn')) return;
// Find the business website link in the Maps panel
const websiteLink = document.querySelector('a[data-item-id="authority"]');
if (!websiteLink) return;
const website = websiteLink.href;
// Create the button
const btn = document.createElement('button');
btn.className = 'eef-email-btn';
btn.textContent = 'Find Email';
btn.onclick = async () => {
btn.textContent = 'Searching...';
btn.disabled = true;
chrome.runtime.sendMessage(
{ action: "enrich", website },
(response) => {
if (response.error) {
btn.textContent = response.error;
btn.style.backgroundColor = '#ef4444';
} else if (response.email) {
btn.textContent = response.email;
btn.style.backgroundColor = '#22c55e';
// Make it clickable to copy
btn.onclick = () => {
navigator.clipboard.writeText(response.email);
btn.textContent = 'Copied!';
setTimeout(() => { btn.textContent = response.email; }, 1500);
};
} else {
btn.textContent = 'No email found';
btn.style.backgroundColor = '#f59e0b';
}
btn.disabled = false;
}
);
};
// Insert after the website link
websiteLink.parentElement.parentElement.after(btn);
}
// Google Maps is a single-page app, so watch for navigation changes
const observer = new MutationObserver(() => {
setTimeout(injectEmailButton, 1000);
});
observer.observe(document.body, { childList: true, subtree: true });
injectEmailButton();
Step 4: Popup for Settings
<!-- popup.html -->
<div style="width: 300px; padding: 16px; font-family: sans-serif;">
<h3>Easy Email Finder</h3>
<div id="balance">Loading...</div>
<label>API Key:</label>
<input type="password" id="apiKey" style="width: 100%; margin: 8px 0;" />
<button id="saveBtn">Save</button>
<p style="font-size: 12px; margin-top: 12px;">
Get your API key at
<a href="https://easyemailfinder.com/developer/docs" target="_blank">
easyemailfinder.com/developer/docs
</a>
</p>
</div>
<script src="popup.js"></script>
// popup.js
document.addEventListener('DOMContentLoaded', async () => {
const data = await chrome.storage.sync.get("eef_api_key");
document.getElementById("apiKey").value = data.eef_api_key || "";
// Get balance
chrome.runtime.sendMessage({ action: "getBalance" }, (resp) => {
const credits = resp?.credits || 0;
document.getElementById("balance").textContent =
`Credits: ${credits} ($${(credits * 0.25).toFixed(2)})`;
});
document.getElementById("saveBtn").onclick = async () => {
const key = document.getElementById("apiKey").value;
await chrome.storage.sync.set({ eef_api_key: key });
window.close();
};
});
Step 5: Load and Test
Open chrome://extensions, enable Developer Mode, click "Load unpacked," and select your extension folder. Navigate to Google Maps, search for a business, and look for the "Find Email" button in the sidebar.
Security Best Practices
- The API key is stored in Chrome's sync storage and never exposed to web pages
- All API calls go through the background service worker, not the content script
- The extension only activates on Google Maps pages
Publishing
To publish on the Chrome Web Store, create a developer account ($5 one-time fee), zip your extension files, and submit for review. Make sure to include a clear privacy policy since you are handling API keys.
Next Steps
Extend the extension to batch-find emails for all visible businesses on the map, add export functionality, or integrate with your CRM. For backend patterns, see our Node.js pipeline guide. For API details, visit easyemailfinder.com/developer/docs.
Ready to find business emails?
Try Easy Email Finder free — get 5 credits to start.
Start Finding Emails