What Is the Element Picker in uBlock Origin? Interactive Filter Creation Explained

The element picker in uBlock Origin is a built-in interactive utility that lets users click on any web page element to automatically generate cosmetic or network filters, enabling one-click creation of custom blocking rules without manual syntax writing.

The element picker is one of uBlock Origin's most powerful features for users who want fine-grained control over their browsing experience. According to the gorhill/uBlock source code, this tool bridges the gap between visual page inspection and filter syntax generation, allowing users to create precise blocking rules by simply clicking on unwanted elements. Understanding how the element picker works internally reveals why it can generate both cosmetic filters (to hide elements) and network filters (to block requests) with high accuracy.

How the Element Picker Works Internally

Triggering the Picker via elementPickerExec

The entry point for the element picker is the µb.elementPickerExec function defined in src/js/ublock.js (lines 34-64). This asynchronous function handles the initialization and script injection process when a user activates the picker from the popup menu or context menu.

// src/js/ublock.js – elementPickerExec (lines 34-64)
µb.elementPickerExec = async function(
    tabId, frameId, targetElement, zap = false,
) {
    if ( vAPI.isBehindTheSceneTabId(tabId) ) { return; }

    this.epickerArgs.target = targetElement || '';
    this.epickerArgs.zap = zap;

    // Load diff library unless we are in "zap" preview mode
    if ( zap !== true ) {
        vAPI.tabs.executeScript(tabId, {
            file: '/lib/diff/swatinem_diff.js',
            runAt: 'document_end',
        });
    }

    // Inject the core picker script
    await vAPI.tabs.executeScript(tabId, {
        file: '/js/scriptlets/epicker.js',
        frameId,
        runAt: 'document_end',
    });

    // Ensure the tab is active after injection
    vAPI.tabs.select(tabId);
};

Injecting the Core Script: epicker.js

Once triggered, the system injects src/js/scriptlets/epicker.js into the target tab. This script contains the DOM inspection logic that identifies the clicked element and extracts its identifying characteristics such as IDs, classes, attributes, and URLs.

Generating Filters from DOM Elements

Creating Cosmetic Filters with cosmeticFilterFromElement

The cosmeticFilterFromElement function in src/js/scriptlets/epicker.js (around lines 93-114) constructs the most specific CSS selector possible for the target element. It prioritizes unique identifiers like IDs, then classes, then attributes, and finally falls back to tag names with structural positioning.

// src/js/scriptlets/epicker.js – cosmeticFilterFromElement (excerpt)
const cosmeticFilterFromElement = function(elem) {
    if ( elem === null || elem.nodeType !== 1 || noCosmeticFiltering ) { return 0; }

    // Build selector from id, class, tag, and attributes
    let selector = '';
    const id = typeof elem.id === 'string' && CSS.escape(elem.id);
    if ( id ) { selector = '#' + id; }

    // … add classes, attributes, and fallback to tag name …
    // (see full implementation for attribute handling)

    // Narrow ambiguous selectors with :nth-of-type when needed
    const parentNode = elem.parentNode;
    if ( safeQuerySelectorAll(parentNode, `:scope > ${selector}`).length > 1 ) {
        selector = `${elem.localName}${selector}`;
        // further disambiguation…
    }

    return selector;   // e.g. "div#adbanner.banner[data-src=\"...\"]"
};

Building Network Filters

For elements that load external resources (images, scripts, iframes), the picker can also generate network filters using netFilterFromElement. This extracts the resource URL and creates a blocking rule that prevents the network request from completing, rather than just hiding the element.

Sending Results to the Background Script

Once the filter is generated, the picker transmits the data back to the background script via vAPI.messaging.send. The message includes the filter type, hostname, and the generated rule string.

// src/js/scriptlets/epicker.js – sending data (lines 311-317)
vAPI.messaging.send('elementPicker', {
    what: 'elementPickerEprom',
    lastNetFilterSession,
    lastNetFilterHostname,
    lastNetFilterUnion,
});

The Zap Preview Mode

The element picker includes a "zap" preview mode that temporarily removes matching elements from the page before the user commits to creating a filter. This allows immediate visual confirmation of what will be blocked.

According to the locale definitions in src/_locales/en/messages.json (line 300), the preview mode "will cause the elements matching the current filter to be removed from the page." When zap is set to true in elementPickerExec, the system skips loading the diff library (swatinem_diff.js) and proceeds directly to script injection for immediate element removal.

Key Source Files and Architecture

The element picker functionality spans several critical files in the gorhill/uBlock repository:

  • src/js/ublock.js – Contains µb.elementPickerExec, the main entry point that handles script injection and zap mode logic.
  • src/js/scriptlets/epicker.js – The core picker script injected into web pages; handles DOM inspection, selector generation (cosmeticFilterFromElement, netFilterFromElement), and messaging.
  • src/js/epicker-ui.js – Manages the user interface overlay that displays generated filters and allows user confirmation or editing.
  • src/_locales/en/messages.json – Contains localized strings including the zap preview mode description.
  • lib/diff/swatinem_diff.js – Optional diff library loaded for advanced selector comparison (skipped in zap mode).

Summary

  • The element picker in uBlock Origin is an interactive utility that converts visual element selection into automatic filter generation.
  • It supports both cosmetic filters (hiding elements via CSS selectors) and network filters (blocking resource requests).
  • The entry point µb.elementPickerExec in src/js/ublock.js orchestrates script injection and handles the zap preview mode.
  • Core logic resides in src/js/scriptlets/epicker.js, which extracts element attributes and constructs specific selectors using cosmeticFilterFromElement.
  • Users can preview changes immediately with zap mode before committing permanent rules, streamlining the custom filter creation process.

Frequently Asked Questions

What is the difference between the element picker and the logger in uBlock Origin?

The element picker is a visual tool for creating new filters by clicking on page elements, while the logger is a diagnostic tool that records all network requests and cosmetic filter applications in real-time. The picker generates filter syntax automatically, whereas the logger helps users analyze existing traffic and filter performance without creating new rules directly.

Can the element picker create network filters as well as cosmetic filters?

Yes, the element picker can generate both cosmetic filters (which hide elements using CSS selectors) and network filters (which block HTTP requests). When you select an element that loads external resources—such as images, scripts, or iframes—the picker uses netFilterFromElement to extract the URL and create a blocking rule that prevents the resource from loading entirely.

How does the zap mode work in the element picker?

Zap mode is a preview feature that temporarily removes elements matching the current filter from the page without saving the rule. When activated via elementPickerExec with zap = true, the system skips loading the diff library and immediately injects the picker script to remove the targeted elements. This allows users to see the visual impact of a filter before committing it permanently, as described in the locale file at src/_locales/en/messages.json.

Where is the element picker code located in the uBlock Origin repository?

The element picker implementation spans multiple files in the gorhill/uBlock repository. The main entry point is src/js/ublock.js, which contains the µb.elementPickerExec function. The core DOM inspection logic lives in src/js/scriptlets/epicker.js, which handles selector generation and messaging. The user interface is managed by src/js/epicker-ui.js, while localized strings (including zap mode descriptions) are stored in src/_locales/en/messages.json.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →