Welcome!

This is a place to share bookmarklets.


How this site works

Scripts are saved as URLs.

To add a script

  1. Go to Add script.
  2. Paste the URL of a RAW JavaScript file.

You can add optional metadata using userscript-like comments.
Supported tags:

  • // @name – if not present, defaults to the URL's filename.
  • // @description
  • // @image – URL to an image that will be displayed on this site. You can add multiple images.
  • // @video – URL to a video. You can add many.

What, How, Why?

What are Bookmarklets?

They are small JavaScript programs stored as browser bookmarks.

When you click the bookmark, the code runs on the current web page, to do things like:

  • modify the page
  • automate actions
  • extract information.

How to install a bookmarklet

There are multiple ways:

  • Drag the Install button to your browser's bookmarks toolbar.
  • (Firefox only) Right-click the Install button and select "Bookmark link".
  • Manually add a new bookmark. Right-click the Install button and select "Copy link address", then create a new bookmark and paste the URL in the URL field.

Why bookmarklets?

Bookmarklets and Userscripts should ideally be implemented as Web Extensions, but verifying that extensions only do what they claim is hard. Although permissions aim to address this issue, they are too broad. So often, a better option is to read and verify the code ourselves.

However, verifying extensions has two challenges: 1. Learning how extensions work and its APIs 2. Accessing the source code. Especially relevant for extensions that can be written as a one-line bookmarklet, it's harder to verify them than to write them as a bookmarklet.

Narrowing permissions' scope would help, but it requires significant coordination and effort, making it feasible only for the most common requested permissions.

Extension platforms should make it easy to read the code, it's the best way to tell what an extension can do. But until then, bookmarklets and userscripts remain better options for many tasks.

Source URL: data:text/javascript,// @name Ingress passcodes auto-inserter // @description copy passcodes from `ingress.fandom.com/wiki/Passcode` and then mass-inserts them in the intel map (() => { const PASSCODE_TAG = '###INGRESS_PASSCODES###\n'; if (window.location.href.includes('ingress.fandom.com/wiki/Passcode')) { // On wiki page - copy passcodes with tag const passcodes = [...document.querySelectorAll("li>code>big")].map(x => x.textContent); navigator.clipboard.writeText(PASSCODE_TAG + passcodes.join('\n')) .then(() => { alert('Passcodes copied to clipboard! Now go to Intel map to use them.'); }) .catch(err => { console.error('Failed to copy passcodes:', err); alert('Failed to copy passcodes to clipboard. Check console for details.'); }); } else if (window.location.href.includes('intel.ingress.com/intel')) { // On Intel map - read and validate passcodes navigator.clipboard.readText() .then(text => { if (!text.startsWith(PASSCODE_TAG)) { throw new Error('Incompatible clipboard content.\n\nPlease go first to the Ingress Wiki ( https://ingress.fandom.com/wiki/Passcode ) and run this script.\nThen come back to the Intel map and run this script again.'); } const passcodes = text .substring(PASSCODE_TAG.length) .split('\n') .filter(code => code.trim()); if (passcodes.length === 0) { throw new Error('No valid passcodes found in clipboard.'); } console.log(`Found ${passcodes.length} passcodes to process`); processPasscodes(passcodes, 0); }) .catch(err => { console.error('Failed to process passcodes:', err); alert(err.message || 'Failed to read passcodes from clipboard. Check console for details.'); }); } else { alert( `Please go first to the Ingress Wiki ( https://ingress.fandom.com/wiki/Passcode ) and run this script to copy the passcodes to clipboard. Then go to the Intel map ( https://intel.ingress.com/intel ) and run this script again to enter the passcodes automatically.`); } // Function to process each passcode with delay function processPasscodes(codes, index) { console.log(`Processing passcode ${index + 1} of ${codes.length}: ${codes[index]}`); if (index >= codes.length) return; const code = codes[index]; // Find passcode input field const inputField = document.getElementById('passcode'); const submitButton = document.getElementById('submit'); if (inputField && submitButton) { // Set the passcode inputField.value = code; // Trigger input event to activate the submit button inputField.dispatchEvent(new Event('input', {bubbles: true})); // Submit the form submitButton.click(); // Wait and process the next code setTimeout(() => { processPasscodes(codes, index + 1); }, 3000); // 3 second delay between submissions } else { alert("Passcode input not found. Try clicking the passcode button in the Ingress UI first."); } } })();
Source code