Create Chrome Extension to Trigger Consecutive Form Submission
In today’s digital landscape, automation can save countless hours of repetitive work. One common task requiring automation is form submission, especially when dealing with multiple entries. This article’ll explore how to build a Chrome extension that automates consecutive form submissions on a specific website.
The Problem
Imagine you need to submit dozens or hundreds of text entries into a web form, one at a time. Each submission requires:
- Entering text into a form field
- Clicking a submit button
- Waiting for the page to reload
- Repeating the process with the next entry
Doing this manually is tedious and error-prone. Let’s build a Chrome extension to automate this workflow.
Solution Overview
Our extension will:
- Provide a popup interface for entering multiple text entries
- Process and clean the input data
- Submit entries one by one
- Maintain state across page reloads
- Continue the process automatically until all entries are submitted

Project Structure
Our extension consists of four main components:
- Manifest file — Defines extension metadata and permissions
- Popup interface — User interface for input
- Content script — Interacts with the webpage
- Background script — Handles page navigation events

Step 1: Setting Up the Manifest
The manifest.json
file is the blueprint of our extension:
{
"manifest_version": 3,
"name": "Auto Input",
"version": "1.0",
"permissions": [
"webNavigation",
"tabs",
"storage"
],
"host_permissions": [
"http://example.com/*"
],
"web_accessible_resources": [
{
"resources": [
"content.js"
],
"matches": [
"http://example.com/*"
]
}
],
"action": {
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": [
"*://example.com/*"
],
"js": [
"content.js"
]
}
],
"background": {
"service_worker": "background.js"
}
}
Key components:
- Permissions: We need webNavigation, tabs, and storage APIs
- Host permissions: Restricts the extension to work only on specific domains
- Content scripts: JavaScript that runs in the context of the web page
- Background script: Runs in the extension’s background
Step 2: Creating the Popup Interface
The popup provides a user-friendly way to input data:
<!DOCTYPE html>
<html>
<head>
<title>Auto Input Extension</title>
<style>
body {
width: 300px;
padding: 10px;
}
textarea {
width: 100%;
height: 150px;
}
</style>
</head>
<body>
<textarea id="inputArray" placeholder="Enter text"></textarea>
<button id="startProcess">Start Process</button>
<script src="popup.js"></script>
</body>
</html>
The popup.js
script processes the input:
document.getElementById('startProcess').addEventListener('click', async () => {
const inputText = document.getElementById('inputArray').value;
// Split by lines, filter empty lines
const stringArray = inputText.split('\n')
.filter(str => str.trim() !== '');
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
// Send the cleaned array
chrome.tabs.sendMessage(tab.id, {
action: 'process',
strings: stringArray
});
});
This script:
- Captures the text from the textarea
- Splits it into lines
- Sends the processed array to the content script
Step 3: Implementing the Content Script
The content script is the workhorse of our extension:
First, we define the IDs for the textarea (or input) and the button that needs to be triggered:
const TEAXTAREA_ID = 'textareaID';
const BUTTON_ID = 'buttonID';
We listen for the initial process command. The user adds the text and clicks start process
button. We store the text that was entered in chrome.storage
in order not to lose it on the next pages:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'process' && request.strings) {
// Store the strings and start processing
chrome.storage.local.set({
stringsToProcess: request.strings,
currentIndex: 0
}, () => {
processStrings();
});
}
});
We assume that after the submission, the page loads the next page:
// Listen for page load events
chrome.runtime.onMessage.addListener((request) => {
if (request.action === 'pageLoaded') {
// Check if we have strings to process and continue
chrome.storage.local.get(['stringsToProcess', 'currentIndex'], (data) => {
if (data.stringsToProcess && data.currentIndex < data.stringsToProcess.length) {
waitForElements().then(() => processStrings());
}
});
}
});
Later, we create the processStrings
function:
- It retrieves stored data from Chrome’s local storage, specifically two items:
stringsToProcess
andcurrentIndex
- It checks if processing is complete. If there are no strings to process or we’ve reached the end of the array, it logs “All strings processed”, clears the storage, and exits
async function processStrings() {
const data = await chrome.storage.local.get(['stringsToProcess', 'currentIndex']);
const { stringsToProcess, currentIndex } = data;
if (!stringsToProcess || currentIndex >= stringsToProcess.length) {
console.log('All strings processed');
// Clear storage when done
chrome.storage.local.remove(['stringsToProcess', 'currentIndex']);
return;
}
const textarea = document.getElementById(TEAXTAREA_ID);
if (textarea) {
textarea.value = stringsToProcess[currentIndex];
const saveButton = document.getElementById(BUTTON_ID);
if (saveButton) {
// Update the index before clicking
await chrome.storage.local.set({ currentIndex: currentIndex + 1 });
saveButton.click();
} else {
console.error('no button');
}
} else {
console.error('no textarea');
}
}
One challenge in web automation is ensuring elements are available before interacting with them. Our waitForElements
function implements a retry mechanism:
/*
This function:
Checks if required elements exist
If not, waits 500ms and tries again
Continues for up to 10 attempts
Uses Promises for clean async handling
*/
function waitForElements(maxAttempts = 10) {
return new Promise((resolve) => {
const checkElements = (attempts = 0) => {
const textarea = document.getElementById(TEAXTAREA_ID);
const button = document.getElementById(BUTTON_ID);
if (textarea && button) {
resolve();
} else if (attempts < maxAttempts) {
setTimeout(() => checkElements(attempts + 1), 500);
}
};
checkElements();
});
}
Key features:
- State Management: Uses
chrome.storage
to maintain the state across page reloads - Element Detection: Waits for form elements to be available
- Sequential Processing: Processes one entry at a time
- Error Handling: Checks for missing elements
Step 4: Creating the Background Script
The background script background.js
monitors page navigation:
chrome.webNavigation.onCompleted.addListener((details) => {
chrome.tabs.sendMessage(details.tabId, { action: 'pageLoaded' });
});
This simple script detects when a page has finished loading and notifies the content script to continue processing.
How It All Works Together
- User Input: The user enters formatted text in the popup and clicks “Start Process”.
- Data Processing: The popup script cleans the input and sends it to the content script.
- Initial Storage: The content script stores the data in
chrome.storage
- First Submission: The content script finds the form elements, fills in the first entry, and clicks submit
- Page Reload: The form submission causes the page to reload
- Continuation: The background script detects the page load and notifies the content script
- Next Entry: The content script retrieves the next entry from storage and continues the process
- Completion: Once all entries are processed, the storage is cleared
State Persistence
To maintain state across page reloads, we use chrome.storage.local:
// Store state
await chrome.storage.local.set({
stringsToProcess: request.strings,
currentIndex: 0
});
// Retrieve state
const data = await chrome.storage.local.get(['stringsToProcess', 'currentIndex']);
This ensures our automation continues even when the page refreshes.
Potential Enhancements
- Progress Indicator: Add a progress bar to show completion status
- Pause/Resume: Allow users to pause and resume the process
- Error Recovery: Implement more robust error handling
4. Configurable Selectors: Allow users to specify different form elements
- Data Validation: Add validation for input format
Conclusion
Building a Chrome extension for consecutive form submission demonstrates the power of browser automation. With just a few files of JavaScript, HTML, and JSON, we’ve created a tool that can save hours of manual work.
The key takeaways from this project:
- Chrome extensions provide powerful APIs for automation
- State management is crucial for processes that span page reloads
3. Asynchronous programming with Promises makes complex workflows manageable
- Error handling and retry mechanisms improve reliability
By understanding these concepts, you can build your automation extensions for various web tasks, saving time and reducing errors in repetitive workflows.
If you liked this article, pls applaud and share with your friends.