At one point, I realized I was typing the same information dozens of times a week — email, phone number, shipping address, GitHub links, job titles. Whether it was job applications, feedback forms, or code sandbox setups, the repetition was maddening.
So I built a JavaScript browser extension that automatically fills in forms based on my own custom templates.
This is not a tutorial for another "Hello World" extension. This is a full-blown walkthrough of how I engineered something practical, personal, and incredibly time-saving — all using raw JavaScript, the Chrome Extensions API, and no frameworks.
Let's build your own autofill assistant that you'll actually use daily.
1. Understanding the Problem and the Chrome Extension Structure
Before writing any JavaScript, I needed to get familiar with how Chrome extensions are structured.
A basic Chrome extension includes:
manifest.json: metadata about your extensioncontent.js: the script that runs inside web pagespopup.html: optional UI to toggle or configurebackground.js: background tasks, message listeners
I created this folder structure:
autofill-extension/
├── manifest.json
├── content.js
├── popup.html
├── popup.js2. Setting Up manifest.json for Chrome V3
Manifest v3 is the latest, and while it's a bit stricter than v2, it's secure and fast.
{
"manifest_version": 3,
"name": "Form AutoFiller",
"version": "1.0",
"description": "Auto-fills web forms with custom user data",
"permissions": ["activeTab", "scripting"],
"action": {
"default_popup": "popup.html"
},
"background": {
"service_worker": "background.js"
},
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content.js"]
}]
}3. Writing the Autofill Logic in content.js
This is where the magic happens.
const autofillData = {
"email": "your.email@example.com",
"name": "John Developer",
"phone": "123-456-7890",
"linkedin": "https://linkedin.com/in/johndev",
"github": "https://github.com/johndev"
};
function fillInputs() {
const inputs = document.querySelectorAll('input, textarea');
inputs.forEach(input => {
const name = input.name.toLowerCase();
for (let key in autofillData) {
if (name.includes(key)) {
input.value = autofillData[key];
input.dispatchEvent(new Event('input', { bubbles: true }));
}
}
});
}
fillInputs();This script finds all text fields and fills them based on name attributes. It's lightweight and surprisingly accurate on 80% of forms.
4. Creating a Popup to Trigger the Script Manually
I wanted to trigger autofill only when needed, not on every tab. So I created a simple popup UI.
<!-- popup.html -->
<!DOCTYPE html>
<html>
<head><title>Autofill</title></head>
<body>
<button id="fill">Fill Form</button>
<script src="popup.js"></script>
</body>
</html>
// popup.js
document.getElementById('fill').addEventListener('click', async () => {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
chrome.scripting.executeScript({
target: { tabId: tab.id },
files: ['content.js']
});
});This uses Chrome's scripting API to inject content.js into the current tab.
Testing and Debugging Your Extension
To test it:
- Go to
chrome://extensions - Enable Developer Mode
- Click "Load unpacked"
- Select the
autofill-extension/folder
Now visit any form, click the extension, and boom — your data appears.
Debugging tips:
- Use
console.loginsidecontent.js - Open DevTools → Console (on the form page) to see what's happening
- Be patient — some fields are tricky and need
dispatchEventto register changes
6. Adding a Custom Config Editor to Store User Data
Hardcoding data isn't ideal. So I added a local storage UI for user inputs.
<!-- popup.html -->
<textarea id="dataInput" placeholder='{"email":"me@site.com"}'></textarea>
<button id="save">Save</button>
<button id="fill">Fill</button>
document.getElementById("save").addEventListener("click", () => {
const raw = document.getElementById("dataInput").value;
localStorage.setItem("autofillData", raw);
});
document.getElementById("fill").addEventListener("click", async () => {
const data = localStorage.getItem("autofillData");
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
chrome.scripting.executeScript({
target: { tabId: tab.id },
func: (autofillData) => {
const inputs = document.querySelectorAll('input, textarea');
inputs.forEach(input => {
const name = input.name.toLowerCase();
for (let key in autofillData) {
if (name.includes(key)) {
input.value = autofillData[key];
input.dispatchEvent(new Event('input', { bubbles: true }));
}
}
});
},
args: [JSON.parse(data)]
});
});Now users can paste their own template and save it for later use. No more code editing.
7. Expanding Compatibility with AI and Natural Language Mapping
Some sites use random names for form fields. So I added AI-driven logic using OpenAI to interpret label names.
(This part is optional, but fun):
// grab nearest label
const label = input.closest('label')?.innerText;
// send label + DOM hints to OpenAI for a matchOr use a keyword-to-field ML model trained on labeled DOM data (outside scope here, but possible with TensorFlow.js).
Final Build, Zip, and Share
Once tested:
- Zip the folder
- Share with friends
- Or upload to the Chrome Web Store (after getting dev approval)
This was the most impact-per-line-of-code project I've ever built. It saves me 2–3 minutes every time I open a form — and that adds up fast.
Final Thoughts
We often overlook the web automation potential of JavaScript outside of frameworks. But pure browser APIs are incredibly powerful. With less than 150 lines of code, I:
- Built a form autofiller
- Made it user-configurable
- Packaged it into a Chrome extension
No React. No NPM. Just old-school, vanilla JS.
And it works beautifully.
Thank you for being a part of the community
Before you go:
- Be sure to clap and follow the writer ️👏️️
- Follow us: X | Medium
- 🚀 Follow our publication, CodeToDeploy, for Daily insights on frontend, AI, productivity & more — built for modern Tech People.
Let's keep building, learning, and shipping — together. 💡