A browser extension that automatically solves Cisco NetAcad quizzes by extracting answer data from quiz endpoints and intelligently selecting correct answers. Built with Webpack and compatible with Chrome, Edge, and Firefox.
- π― Auto-solve quizzes - Automatically selects correct answer(s) when you visit a quiz
- π±οΈ Click-to-solve - Click a question to highlight and select the correct option(s)
- β¨οΈ Ctrl+Hover solve - Hold Ctrl while hovering answers to select correct ones
- π Multiple question types - Handles MCQ, matching, dropdowns, fill-in-the-blanks, yes/no, table dropdowns, and text input questions
- π Browser support - Works on Chrome, Edge, Firefox, and other Chromium-based browsers
- π‘ Status indicator - Popup shows connection status to NetAcad
The extension uses a two-part architecture: background script + content script.
NetAcad Server (components.json)
β
Background Script (Detects API calls)
β
Content Script (Processes DOM & Answers)
β
User Sees Correct Answers Selected
-
Detection Phase
- Background script monitors network requests for
components.jsonAPI calls - NetAcad loads quiz data via this API endpoint with all answer information
- Extension intercepts and sends the URL to the content script
- Background script monitors network requests for
-
Data Fetching
- Content script fetches the
components.jsonand parses the quiz structure - Each question has metadata including
_id,_items[], and_shouldBeSelected/_isCorrectflags - Answer data is extracted and stored in memory
- Content script fetches the
-
DOM Analysis
- Extension searches the quiz DOM (using CSS selectors, iframes, and shadow DOM)
- Identifies each question type based on the component structure
- Maps answer data to DOM elements (inputs, buttons, dropdowns, etc.)
-
Auto-Solve
- When user clicks a question: extension finds the correct answer element and clicks/selects it
- Event listeners are attached with WeakSets to prevent duplicate handlers
- Supports both click events and Ctrl+hover interactions
| Type | Data Source | Interaction |
|---|---|---|
| Basic MCQ | _shouldBeSelected boolean |
Click radio/checkbox inputs |
| Matching | question/answer pairs |
Click matching pairs |
| Dropdown Select | _options[] with _isCorrect |
Click dropdown option |
| Yes/No | _graphic + _shouldBeSelected |
Click Yes/No buttons |
| Fill Blanks | preText, postText, _options[] |
Select dropdown blanks |
| Text Input | _options.text with text match |
Click answer buttons |
| Table Dropdown | _columns + _options |
Click table cell inputs |
Coming soon to Chrome Web Store and Firefox Add-ons.
- Clone/download this repository
- Run
npm install && npm run build - Go to
chrome://extensions/ - Enable Developer mode (top right)
- Click Load unpacked and select the
dist/folder - Visit https://www.netacad.com/ and start a quiz
- Clone/download this repository
- Run
npm install && npm run build - Go to
about:debugging#/runtime/this-firefox - Click Load Temporary Add-on and select
dist/manifest.json - Visit https://www.netacad.com/ and start a quiz
- Navigate to https://www.netacad.com/ and open a quiz
- Wait for the popup to show "NetAcad page detected"
Method 1: Click to Solve
- Click on any quiz question β Correct answer(s) auto-select
Method 2: Ctrl+Hover
- Hold Ctrl and hover over answer options β Selected options highlight
Method 3: Auto-Solve (on page load)
- If auto-solve is enabled, answers appear as soon as the quiz loads
- π’ Green dot with "NetAcad page detected" = Extension ready
- β« Gray dot with "Open a NetAcad page" = Not on a quiz page
- The "Tip Me!" button links to Ko-fi if you want to support development
your-netacad-solver/
βββ src/
β βββ background/
β β βββ background.js # Monitors network requests
β βββ content/
β β βββ content.js # Main quiz processing (Firefox-compatible)
β β βββ domHelper.js # Deep DOM search utilities
β βββ chrome/
β β βββ background.js # Chrome-specific network interception
β β βββ content.js # Chrome-specific question handling
β β βββ popup.js # Popup UI logic
β β βββ popup.html # Popup interface
β β βββ domHelper.js # Chrome DOM utilities
β βββ firefox/
β β βββ background.js # Firefox-specific handlers
β β βββ content.js # Firefox content script
β β βββ manifest.json # Firefox manifest v3
β βββ popup.js # Shared popup logic
β βββ popup.html # Shared popup template
β βββ manifest.json # Chrome manifest v3
β βββ manifest-v2.json # Legacy manifest
βββ webpack.common.js # Shared webpack config
βββ webpack.dev.js # Development config
βββ webpack.prod.js # Production config
βββ package.json # Dependencies & scripts
Background Script (src/chrome/background.js or src/background/background.js)
// Listens for API calls to components.json
browser.webRequest.onSendHeaders.addListener(({url, tabId}) => {
// When detected: browser.tabs.sendMessage(tabId, {componentsUrl: url})
// This wakes up the content script with the quiz data endpoint
}, {urls: ['https://*.netacad.com/*/components.json']});This approach intercepts the network request without needing API keys or authenticationβthe data is already being loaded by NetAcad.
Key Functions:
setComponents(url)- Fetchescomponents.jsonand parses quiz structuredetectQuestionType(component)- Identifies question type from data structureprocessComponent(component, questionDiv)- Handles different question typesdeepHtmlSearch(document, selector)- Searches iframes and shadow DOM- Event Listeners - Attaches click/hover handlers with WeakSet to prevent duplicates
Example: Basic MCQ Processing
// For each item in the question:
// - Find the input element (radio or checkbox)
// - Add click listener
// - If _shouldBeSelected is true: pre-click or highlight
// - For Ctrl+hover: conditional click on mouseoverNetAcad quizzes use:
- iframes - Nested frames with quiz content
- Shadow DOM - Encapsulated component styles
- Dynamic IDs - CSS-escaped class names like
#{escapeId}__${i}-input
The deepHtmlSearch() function recursively searches through all of these:
// 1. Direct DOM query
// 2. Search all iframes recursively
// 3. Search shadow DOM in elements with shadowRoot
// 4. Return first match foundBasic MCQ from components.json:
{
"_id": "question-123",
"_items": [
{ "_shouldBeSelected": true, "text": "Correct Answer" },
{ "_shouldBeSelected": false, "text": "Wrong Answer" }
]
}Matching Question:
{
"_items": [
{ "question": "Q1", "answer": "A1" },
{ "question": "Q2", "answer": "A2" }
]
}- Chrome/Edge/Brave: Uses Chrome-specific APIs (
chrome.webRequest) - Firefox: Uses WebExtension APIs (
browser.webRequest) - Polyfill:
webextension-polyfillprovides consistent API across browsers
# Install dependencies
npm install
# Start dev server with file watching
npm start
# Build for production
npm run build
# Output goes to dist/Adding a new question type:
- Update
detectQuestionType()to identify your new type - Create
processNewType()function - Add case in the switch statement in
main() - Test by checking the DOM structure in your quiz
Debugging:
// Enable console logging in extension
// Open DevTools on the quiz page: Right-click β Inspect β Console
// Look for [NetAcad Helper] messagesTo view background script logs:
- Go to
chrome://extensions/ - Click Details on your extension
- Click background.js under "Inspecting views"
Development Workflow:
- Make changes to
src/files - Run
npm startfor file watching - Go to
chrome://extensions/ - Click the refresh icon on your extension to reload
- Test on a NetAcad quiz page
Uses Webpack 5 with separate configs:
webpack.common.js- Shared config, Babel transpilationwebpack.dev.js- Source maps, no minification, faster buildswebpack.prod.js- Minification, Terser plugin, optimized output
Each browser (Chrome/Firefox) gets its own manifest and code tree for compatibility.
See CHANGELOG.md for detailed updates and improvements.
If you find bugs or have feature requests, check the GitHub issues or consider supporting development via Ko-fi.
This extension is for educational purposes. Users are responsible for ensuring their use complies with NetAcad's terms of service and their educational institution's policies.
Built with β€οΈ using Webpack, JavaScript, and WebExtension APIs
- Build the extension (npm run build)
- Replace dist/manifest.json with src/manifest-v2.json (or package separately for Firefox)
- Open about:debugging#/runtime/this-firefox
- Click Load Temporary Add-on and select your Firefox package/manifest
MIT