A bookmarklet runs JavaScript on the page you’re already on. This can be very convenient versus trying to get around security and bot-busting, especially when the site you are on doesn't have any convenient automation features.
You can do a lot with them. You could turn the background to dark mode, swap out words or URLs across an entire page, or add interactive elements.
This is a cool one which removes popup layers on web sites, you know like "agree to our terms before reading" and stuff:
javascript:(function()%7B(function () %7Bvar i%2C elements %3D document.querySelectorAll('body *')%3Bfor (i %3D 0%3B i < elements.length%3B i%2B%2B) %7Bif (getComputedStyle(elements%5Bi%5D).position %3D%3D%3D 'fixed') %7Belements%5Bi%5D.parentNode.removeChild(elements%5Bi%5D)%3B%7D%7D%7D)()%7D)()
Another fun one allows you to edit the content of the current page, like virtual graffiti:
javascript:document.body.contentEditable %3D %27true%27%3B document.designMode%3D%27on%27%3B void 0
Here is how to make one yourself.
Try One Out
- Make a new bookmark in your browser (right-click the bookmarks bar and select “Add Page…”).
- For the name, type something like
Prince Me!
. - Copy this code and paste it into the bookmark’s location field:
javascript:(function(){document.body.style.background = 'purple';})();
- Visit any site, click your new bookmark, and the background should change (most of the time).
How to Make Your Own
You only need three steps:
- Write the JavaScript you want to run (start by testing in the browser console).
- Add
javascript:
to the front. - Wrap it in an IIFE (Immediately Invoked Function Expression) so the page runs it cleanly without reloading.
Example, replace “AI” with “ball sack” everywhere on a page:
javascript:document.body.innerHTML = document.body.innerHTML.replace(/AI/g, "ball sack").replace(/AI/g, "Ball Sack");
If you try that directly, the page may refresh or break some styles. Wrapping it in an IIFE fixes this most of the time:
javascript:(function(){
document.body.innerHTML = document.body.innerHTML.replace(/AI/g, "ball sack").replace(/AI/g, "ball sack");
})();
That’s the general template you can use:
javascript:(function(){ /* your code here */ })();
Quicker Debugging
Updating the bookmark every time you change the code can be slow. You can test in the browser’s location bar instead:
Paste your code there with javascript:
at the front.
Note: browsers usually strip javascript:
when you paste, so you’ll have to retype it.
Editing Bookmarklets
When you save a bookmarklet, the browser removes newlines and indentation, making it hard to read. Two ways to handle this:
- Keep a copy in a text file (or a code repository like GitHub).
- Use a tool like JSBeautifier to reformat it before editing. Then paste it back into the bookmark when ready.
Useful JavaScript You Can Test First
Before you put code into a bookmarklet, it’s best to test it in the console.
Open the browser console
Windows or Linux
- Chrome, Edge, Brave: F12 or Ctrl+Shift+I, then click Console
- Firefox: F12 or Ctrl+Shift+K for Console
Mac
- Chrome, Edge, Brave: Cmd+Option+I, then Console
- Firefox: Cmd+Option+K
- Safari: enable Develop menu in Preferences, then Option+Cmd+C
Use console.log for quick checks
console.log
prints to the Console. It’s the easiest way to see what your code is doing.
console.log('Starting script');
console.log({ location: window.location.href });
You can also use it for lightweight notifications during a bookmarklet run.
console.log('Changed background to pink');
Select elements on the page
By tag name
Returns a live HTMLCollection.
var inputs = document.getElementsByTagName('input');
console.log('Found', inputs.length, 'inputs');
By id
Returns a single element or null.
var searchBox = document.getElementById('search');
By class name
Returns a live HTMLCollection.
var errors = document.getElementsByClassName('error');
With CSS selectors
querySelector
returns the first match.
querySelectorAll
returns a static NodeList.
var firstButton = document.querySelector('button.primary');
var allLinks = document.querySelectorAll('a[href^="https://"]');
Check if a string contains text
Use indexOf("some text")
. It returns the position or -1 if not found.
var title = document.title;
if (title.indexOf('Pricing') >= 0) {
console.log('This looks like a pricing page');
}
Case-insensitive check:
if (title.toLowerCase().indexOf('pricing') >= 0) { /* ... */ }
Work with parents and children
var el = document.querySelector('.item');
/* parent */
var parent = el.parentElement;
/* nearest matching ancestor */
var card = el.closest('.card');
/* children collection */
var kids = el.children; // HTMLCollection of element children
var firstKid = el.firstElementChild;
var next = el.nextElementSibling;
Turn collections into arrays
Many DOM methods return HTMLCollection or NodeList. Convert them so you can use array helpers like find
, filter
, and map
.
var inputs = Array.from(document.getElementsByTagName('input'));
Now you can iterate with full array methods.
Find a specific input with Array.find
find
returns the first matching element or undefined
.
var matchingInput = inputs.find(function(item) {
return item.defaultValue && item.defaultValue.indexOf('Inspect any URL') >= 0;
});
if (matchingInput) {
console.log('Found:', matchingInput);
}
Arrow function version:
var matchingInput = inputs.find(i =>
typeof i.defaultValue === 'string' &&
i.defaultValue.indexOf('Inspect any URL') >= 0
);
Act on what you found
Once you have the element, you can change it or click related controls.
if (matchingInput) {
matchingInput.value = 'https://example.com';
/* example: click the next sibling button if it exists */
var btn = matchingInput.nextElementSibling;
if (btn && btn.tagName === 'BUTTON') btn.click();
}
Combine these in a bookmarklet
Test in the console first. When it works, wrap it and prefix with javascript:
.
javascript:(function(){
var inputs = Array.from(document.getElementsByTagName('input'));
var target = inputs.find(i =>
typeof i.defaultValue === 'string' &&
i.defaultValue.toLowerCase().indexOf('inspect any url') >= 0
);
if (target) {
target.value = 'https://example.com';
console.log('Filled target input');
var submit = target.form && target.form.querySelector('button, input[type="submit"]');
if (submit) {
submit.click();
console.log('Submitted form');
} else {
console.log('Submit control not found');
}
} else {
console.log('Target input not found');
}
})();
Small patterns you will reuse
Safe text replace across the page
Be careful with innerHTML
because it re-parses the whole DOM. Safer for text-only changes:
function replaceText(node, from, to) {
if (node.nodeType === Node.TEXT_NODE) {
node.nodeValue = node.nodeValue.replace(from, to);
} else {
Array.from(node.childNodes).forEach(function(child){
replaceText(child, from, to);
});
}
}
// usage
replaceText(document.body, /cloud/gi, 'butt');
Wrap for a bookmarklet when you’re happy with it.
Guard against missing elements
Avoid errors when something isn’t on the page.
var el = document.querySelector('#search');
if (!el) {
console.log('Search box not found');
} else {
el.value = 'test';
}
Time your code
Measure how long something takes.
console.time('replace');
replaceText(document.body, /cloud/gi, 'butt');
console.timeEnd('replace');
Test each snippet in the console first, then wrap it in a bookmarklet when it does what you want.