Build a Password Strength Checker Extension: Complete Tutorial
Password security remains one of the most critical concerns in digital safety today. With data breaches affecting millions of users annually, building a password strength checker extension provides genuine value to Chrome users. This comprehensive tutorial will guide you through creating a fully functional password strength extension that analyzes passwords in real-time, provides visual feedback, and helps users create more secure credentials.
In this tutorial, you will learn how to build a Chrome extension using Manifest V3 that evaluates password strength based on multiple criteria, displays a visual strength meter, and offers actionable recommendations for improvement. Whether you are a beginner to Chrome extension development or an experienced developer looking to expand your portfolio, this project demonstrates essential concepts that apply to real-world security tools.
Why Build a Password Strength Checker Extension?
The need for password security tools has never been greater. According to recent cybersecurity studies, over 80% of data breaches involve compromised passwords. Users often create weak passwords because they lack understanding of what makes a password secure or simply do not have tools to evaluate their password strength in real-time.
Building a password strength checker extension addresses several important use cases. First, it provides immediate feedback when users create new passwords on websites. Second, it helps users understand the components of strong passwords through visual indicators. Third, it encourages better password hygiene without requiring users to install separate password manager applications.
From a development perspective, this project teaches you valuable skills including how to work with content scripts to interact with webpage forms, how to implement real-time analysis algorithms, how to create responsive UI elements that blend with different website designs, and how to handle sensitive user input securely within the browser extension environment.
Project Overview and Architecture
Before diving into the code, let us establish a clear understanding of what our password strength checker extension will do. The extension will inject a content script into password input fields across websites, monitor user input in real-time, evaluate the password against multiple strength criteria, and display a visual indicator showing the password strength level.
Our password strength analysis will consider several factors: password length, presence of uppercase letters, presence of lowercase letters, presence of numbers, presence of special characters, and avoidance of common patterns or dictionary words. Each factor contributes to an overall strength score that we will translate into easy-to-understand visual feedback.
The extension architecture follows the Manifest V3 specification, which is the current standard for Chrome extensions. We will use content scripts to interact with password fields, a popup interface for detailed settings, and background scripts for any API communication if needed in future expansions.
Setting Up the Project Structure
Every Chrome extension begins with a manifest file that defines the extension’s capabilities and permissions. Create a new folder for your project and add the following manifest.json file:
{
"manifest_version": 3,
"name": "Password Strength Checker",
"version": "1.0",
"description": "Analyze password strength in real-time and get security recommendations",
"permissions": ["activeTab", "scripting"],
"host_permissions": ["<all_urls>"],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"],
"css": ["styles.css"]
}
],
"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"
}
}
This manifest file grants the extension the necessary permissions to run on all websites and inject our content scripts. The host permissions with <all_urls> allow the extension to analyze passwords on any website where users need to enter credentials.
Creating the Password Analysis Logic
The core of our extension lies in the password analysis algorithm. Create a new file called analyzer.js that will contain the strength evaluation logic. This separation of concerns makes the code maintainable and allows for easy updates to the analysis algorithm without modifying other parts of the extension.
// analyzer.js - Password strength analysis logic
const StrengthAnalyzer = {
// Scoring weights for different criteria
weights: {
length: 3,
uppercase: 2,
lowercase: 2,
numbers: 2,
specialChars: 3,
noCommonPatterns: 4,
noRepeatingChars: 2
},
// Common password patterns to detect
commonPatterns: [
'password', '123456', 'qwerty', 'abc123', 'letmein',
'welcome', 'admin', 'login', 'master', 'dragon'
],
// Analyze password and return detailed results
analyze(password) {
if (!password || password.length === 0) {
return this.getEmptyResult();
}
let score = 0;
const checks = {
hasMinLength: password.length >= 8,
hasGoodLength: password.length >= 12,
hasUppercase: /[A-Z]/.test(password),
hasLowercase: /[a-z]/.test(password),
hasNumbers: /[0-9]/.test(password),
hasSpecialChars: /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(password),
noCommonPatterns: !this.containsCommonPattern(password),
noRepeatingChars: !this.hasRepeatingChars(password)
};
// Calculate base score
if (checks.hasMinLength) score += this.weights.length;
if (checks.hasGoodLength) score += this.weights.length;
if (checks.hasUppercase) score += this.weights.uppercase;
if (checks.hasLowercase) score += this.weights.lowercase;
if (checks.hasNumbers) score += this.weights.numbers;
if (checks.hasSpecialChars) score += this.weights.specialChars;
if (checks.noCommonPatterns) score += this.weights.noCommonPatterns;
if (checks.noRepeatingChars) score += this.weights.noRepeatingChars;
// Bonus points for character diversity
const uniqueChars = new Set(password).size;
score += Math.min(uniqueChars / password.length * 5, 5);
return {
score: Math.min(score, 100),
level: this.getStrengthLevel(score),
checks: checks,
feedback: this.generateFeedback(checks, password)
};
},
getStrengthLevel(score) {
if (score < 20) return 'very-weak';
if (score < 40) return 'weak';
if (score < 60) return 'fair';
if (score < 80) return 'strong';
return 'very-strong';
},
containsCommonPattern(password) {
const lowerPassword = password.toLowerCase();
return this.commonPatterns.some(pattern =>
lowerPassword.includes(pattern)
);
},
hasRepeatingChars(password) {
return /(.)\1{2,}/.test(password);
},
generateFeedback(checks, password) {
const suggestions = [];
if (!checks.hasMinLength) {
suggestions.push('Use at least 8 characters');
}
if (!checks.hasGoodLength) {
suggestions.push('Consider using 12+ characters for better security');
}
if (!checks.hasUppercase) {
suggestions.push('Add uppercase letters (A-Z)');
}
if (!checks.hasLowercase) {
suggestions.push('Add lowercase letters (a-z)');
}
if (!checks.hasNumbers) {
suggestions.push('Include numbers (0-9)');
}
if (!checks.hasSpecialChars) {
suggestions.push('Add special characters (!@#$%^&*)');
}
if (!checks.noCommonPatterns) {
suggestions.push('Avoid common words and patterns');
}
if (!checks.noRepeatingChars) {
suggestions.push('Avoid repeating characters');
}
if (suggestions.length === 0) {
suggestions.push('Great password! Consider making it even longer');
}
return suggestions;
},
getEmptyResult() {
return {
score: 0,
level: 'none',
checks: {},
feedback: ['Start typing to check password strength']
};
}
};
// Export for use in content script
if (typeof module !== 'undefined' && module.exports) {
module.exports = StrengthAnalyzer;
}
This analyzer provides a comprehensive evaluation system that considers multiple factors. The scoring algorithm awards points for each criterion met, with bonus points for character diversity. The feedback generation provides actionable suggestions that help users improve their passwords.
Creating the Content Script
The content script is the bridge between the extension and web pages. It detects password input fields, monitors user input, and displays the strength indicator. Create content.js:
// content.js - Injected into web pages
// Import the analyzer (will be bundled or included)
const StrengthAnalyzer = {
weights: {
length: 3,
uppercase: 2,
lowercase: 2,
numbers: 2,
specialChars: 3,
noCommonPatterns: 4,
noRepeatingChars: 2
},
commonPatterns: [
'password', '123456', 'qwerty', 'abc123', 'letmein',
'welcome', 'admin', 'login', 'master', 'dragon'
],
analyze(password) {
if (!password || password.length === 0) {
return this.getEmptyResult();
}
let score = 0;
const checks = {
hasMinLength: password.length >= 8,
hasGoodLength: password.length >= 12,
hasUppercase: /[A-Z]/.test(password),
hasLowercase: /[a-z]/.test(password),
hasNumbers: /[0-9]/.test(password),
hasSpecialChars: /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(password),
noCommonPatterns: !this.containsCommonPattern(password),
noRepeatingChars: !this.hasRepeatingChars(password)
};
if (checks.hasMinLength) score += this.weights.length;
if (checks.hasGoodLength) score += this.weights.length;
if (checks.hasUppercase) score += this.weights.uppercase;
if (checks.hasLowercase) score += this.weights.lowercase;
if (checks.hasNumbers) score += this.weights.numbers;
if (checks.hasSpecialChars) score += this.weights.specialChars;
if (checks.noCommonPatterns) score += this.weights.noCommonPatterns;
if (checks.noRepeatingChars) score += this.weights.noRepeatingChars;
const uniqueChars = new Set(password).size;
score += Math.min(uniqueChars / password.length * 5, 5);
return {
score: Math.min(score, 100),
level: this.getStrengthLevel(score),
checks: checks,
feedback: this.generateFeedback(checks, password)
};
},
getStrengthLevel(score) {
if (score < 20) return 'very-weak';
if (score < 40) return 'weak';
if (score < 60) return 'fair';
if (score < 80) return 'strong';
return 'very-strong';
},
containsCommonPattern(password) {
const lowerPassword = password.toLowerCase();
return this.commonPatterns.some(pattern =>
lowerPassword.includes(pattern)
);
},
hasRepeatingChars(password) {
return /(.)\1{2,}/.test(password);
},
generateFeedback(checks, password) {
const suggestions = [];
if (!checks.hasMinLength) suggestions.push('Use at least 8 characters');
if (!checks.hasGoodLength) suggestions.push('Consider using 12+ characters');
if (!checks.hasUppercase) suggestions.push('Add uppercase letters');
if (!checks.hasLowercase) suggestions.push('Add lowercase letters');
if (!checks.hasNumbers) suggestions.push('Include numbers');
if (!checks.hasSpecialChars) suggestions.push('Add special characters');
if (!checks.noCommonPatterns) suggestions.push('Avoid common words');
if (!checks.noRepeatingChars) suggestions.push('Avoid repeating characters');
if (suggestions.length === 0) {
suggestions.push('Great password! Consider making it even longer');
}
return suggestions;
},
getEmptyResult() {
return {
score: 0,
level: 'none',
checks: {},
feedback: ['Start typing to check password strength']
};
}
};
// Find all password input fields on the page
function findPasswordFields() {
const selectors = [
'input[type="password"]',
'input:not([type])',
'input[name*="pass"]',
'input[id*="pass"]',
'input[placeholder*="pass"]'
];
const fields = [];
selectors.forEach(selector => {
document.querySelectorAll(selector).forEach(field => {
if (!fields.includes(field) && field.type !== 'text') {
fields.push(field);
}
});
});
return fields;
}
// Create and inject the strength indicator UI
function createStrengthIndicator(inputField) {
const container = document.createElement('div');
container.className = 'pstrength-container';
const meterWrapper = document.createElement('div');
meterWrapper.className = 'pstrength-meter';
const meterFill = document.createElement('div');
meterFill.className = 'pstrength-fill';
meterFill.style.width = '0%';
const label = document.createElement('div');
label.className = 'pstrength-label';
label.textContent = 'Password Strength:';
const strengthText = document.createElement('span');
strengthText.className = 'pstrength-text';
strengthText.textContent = 'Enter password';
const feedback = document.createElement('div');
feedback.className = 'pstrength-feedback';
meterWrapper.appendChild(meterFill);
container.appendChild(label);
container.appendChild(strengthText);
container.appendChild(meterWrapper);
container.appendChild(feedback);
// Insert after the input field
inputField.parentNode.insertBefore(container, inputField.nextSibling);
return { container, meterFill, strengthText, feedback };
}
// Update the strength indicator based on analysis
function updateIndicator(indicator, result) {
const { meterFill, strengthText, feedback } = indicator;
// Update meter width
meterFill.style.width = `${result.score}%`;
// Update color based on strength level
const colors = {
'very-weak': '#dc3545',
'weak': '#ffc107',
'fair': '#fd7e14',
'strong': '#20c997',
'very-strong': '#28a745',
'none': '#6c757d'
};
const labels = {
'very-weak': 'Very Weak',
'weak': 'Weak',
'fair': 'Fair',
'strong': 'Strong',
'very-strong': 'Very Strong',
'none': 'Enter password'
};
meterFill.style.backgroundColor = colors[result.level] || colors.none;
strengthText.textContent = labels[result.level] || labels.none;
strengthText.style.color = colors[result.level] || colors.none;
// Update feedback
feedback.innerHTML = result.feedback.map(tip => `<p>${tip}</p>`).join('');
}
// Initialize password field monitoring
function initializeFields() {
const passwordFields = findPasswordFields();
passwordFields.forEach(field => {
// Skip if already initialized
if (field.dataset.pstrengthInitialized) return;
field.dataset.pstrengthInitialized = 'true';
const indicator = createStrengthIndicator(field);
// Monitor input changes
field.addEventListener('input', () => {
const result = StrengthAnalyzer.analyze(field.value);
updateIndicator(indicator, result);
});
// Handle password visibility toggle if present
const toggleButton = field.parentElement?.querySelector(
'button[aria-label*="show"], button[aria-label*="visibility"], input[type="checkbox"]'
);
if (toggleButton) {
toggleButton.addEventListener('click', () => {
setTimeout(() => {
const result = StrengthAnalyzer.analyze(field.value);
updateIndicator(indicator, result);
}, 100);
});
}
});
}
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeFields);
} else {
initializeFields();
}
// Watch for dynamically added password fields
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.addedNodes.length > 0) {
initializeFields();
}
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
This content script provides comprehensive password field detection and real-time analysis. It uses a MutationObserver to detect dynamically added password fields, ensuring the extension works on single-page applications and websites that load content dynamically.
Styling the Strength Indicator
Create a stylesheet that makes the strength indicator visually appealing and compatible with different website designs:
/* styles.css - Password strength indicator styling */
.pstrength-container {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
margin-top: 8px;
padding: 12px;
background: #f8f9fa;
border-radius: 6px;
max-width: 400px;
}
.pstrength-label {
font-size: 12px;
color: #6c757d;
margin-bottom: 4px;
font-weight: 500;
}
.pstrength-text {
font-size: 14px;
font-weight: 600;
margin-bottom: 8px;
display: block;
}
.pstrength-meter {
height: 6px;
background: #e9ecef;
border-radius: 3px;
overflow: hidden;
margin-bottom: 8px;
}
.pstrength-fill {
height: 100%;
transition: width 0.3s ease, background-color 0.3s ease;
border-radius: 3px;
}
.pstrength-feedback {
font-size: 12px;
color: #495057;
}
.pstrength-feedback p {
margin: 4px 0;
padding: 2px 0;
}
/* Dark mode support */
@media (prefers-color-scheme: dark) {
.pstrength-container {
background: #2d2d2d;
}
.pstrength-label {
color: #adb5bd;
}
.pstrength-feedback {
color: #ced4da;
}
.pstrength-meter {
background: #495057;
}
}
/* Integration with common form styles */
input + .pstrength-container {
margin-top: 8px;
}
/* Ensure visibility on different backgrounds */
.pstrength-container {
background: rgba(248, 249, 250, 0.95);
backdrop-filter: blur(4px);
}
The styles include dark mode support and ensure the indicator is visible regardless of the website’s color scheme. The backdrop filter adds a modern look while ensuring text readability.
Creating the Popup Interface
While the content script handles inline analysis, users often want additional information and settings. Create a popup interface:
<!-- popup.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Password Strength Checker</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
width: 320px;
padding: 20px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #fff;
}
h1 {
font-size: 18px;
margin-bottom: 16px;
color: #333;
}
.section {
margin-bottom: 20px;
}
.section h2 {
font-size: 14px;
color: #666;
margin-bottom: 8px;
}
.criteria {
list-style: none;
}
.criteria li {
padding: 6px 0;
font-size: 13px;
color: #555;
display: flex;
align-items: center;
}
.criteria li::before {
content: '○';
margin-right: 8px;
color: #999;
}
.criteria li.met::before {
content: '●';
color: #28a745;
}
.tips {
background: #f8f9fa;
padding: 12px;
border-radius: 6px;
}
.tips p {
font-size: 12px;
color: #555;
margin-bottom: 8px;
}
.tips p:last-child {
margin-bottom: 0;
}
.footer {
font-size: 11px;
color: #999;
text-align: center;
margin-top: 16px;
}
</style>
</head>
<body>
<h1>Password Strength Checker</h1>
<div class="section">
<h2>Strong Password Criteria</h2>
<ul class="criteria">
<li id="length">At least 12 characters</li>
<li id="uppercase">Uppercase letters (A-Z)</li>
<li id="lowercase">Lowercase letters (a-z)</li>
<li id="numbers">Numbers (0-9)</li>
<li id="special">Special characters (!@#$...)</li>
<li id="unique">No common patterns</li>
</ul>
</div>
<div class="section">
<h2>Security Tips</h2>
<div class="tips">
<p>Use a unique password for each account</p>
<p>Consider using a password manager</p>
<p>Enable two-factor authentication when available</p>
<p>Never share passwords via email or chat</p>
</div>
</div>
<div class="footer">
Password Strength Checker Extension
</div>
<script src="popup.js"></script>
</body>
</html>
The popup provides users with quick reference information about what makes a strong password, reinforcing the inline feedback with educational content.
// popup.js
document.addEventListener('DOMContentLoaded', () => {
// Get the active tab to analyze any password fields
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (chrome.runtime.lastError) {
console.error('Error getting active tab:', chrome.runtime.lastError);
return;
}
// The popup can display static information
// Real-time analysis happens in the content script
});
});
Testing Your Extension
Before publishing, thoroughly test your extension in development mode. Open Chrome and navigate to chrome://extensions/. Enable “Developer mode” in the top right corner. Click “Load unpacked” and select your extension folder.
Test the extension on various websites that have password forms. Try creating accounts on different platforms and verify that the strength indicator appears correctly. Test edge cases such as very long passwords, passwords with only special characters, and passwords that contain common words.
Pay attention to how the indicator appears on different website designs. The extension should be visible but not obtrusive. If the indicator overlaps with other page elements or appears in unexpected locations, you may need to adjust the positioning logic in the content script.
Best Practices and Security Considerations
When building password-related extensions, security must be the top priority. Never store or transmit password data. Our implementation analyzes passwords locally within the content script and does not send any data anywhere. This is crucial for user trust and for passing Chrome Web Store review.
Respect user privacy by clearly explaining what your extension does and does not do. The extension description should explicitly state that passwords are analyzed locally and never leave the user’s browser.
Handle the extension’s permissions minimally. We request activeTab and scripting permissions, which are necessary for the core functionality. Avoid requesting unnecessary permissions that might alarm users or cause review issues.
Implement proper error handling to prevent the extension from breaking websites. Use try-catch blocks around DOM manipulations and provide graceful fallbacks if the password analysis fails.
Publishing Your Extension
Once you have tested the extension thoroughly, you can publish it to the Chrome Web Store. First, create a ZIP file of your extension folder, making sure to exclude any development files. Navigate to the Chrome Web Store Developer Dashboard and create a new item. Upload your ZIP file and fill in the required information including the extension name, description, and screenshots.
The review process typically takes a few days. During review, Google will check for any security issues, proper permission usage, and compliance with their policies. Be prepared to make adjustments if reviewers identify any concerns.
Conclusion
Congratulations! You have built a complete password strength checker extension that provides real-time analysis, visual feedback, and helpful suggestions for improving password security. This project demonstrates essential Chrome extension development concepts including Manifest V3 configuration, content script injection, DOM manipulation, and cross-browser compatibility.
The extension you built follows security best practices by keeping all password analysis local and never transmitting sensitive data. Users can confidently use the extension knowing their password information remains private.
Consider expanding this project with additional features such as a password generator, integration with password managers, or the ability to save strength statistics. Each enhancement provides additional value while teaching you more about Chrome extension development.
Building useful tools like this password strength checker is an excellent way to develop your extension development skills while creating products that genuinely help people stay safer online. Keep experimenting, keep learning, and happy coding!