What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Find the checkbox inputs inside the correct form or container, inspect each element’s current state, and click only the ones that are not selected. This state-aware loop selects several boxes without accidentally unchecking boxes that were already selected.

The safe pattern for selecting multiple checkboxes

A checkbox is a toggle. Calling click() on an already-selected box turns it off, so a loop that blindly clicks every match is not idempotent. The reliable sequence is:

  1. Scope a locator to the intended form, fieldset, or container.
  2. Collect the matching checkbox elements.
  3. Read each element’s selected state.
  4. Click only when the state is unchecked.
  5. Verify the final state or the form result.

In Python, Selenium exposes this state through is_selected(). In Java, the method is isSelected(). The selector below is illustrative; replace #preferences with a stable selector from your page.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from selenium.webdriver.common.by import By

boxes = driver.find_elements(
    By.CSS_SELECTOR,
    "#preferences input[type='checkbox']"
)

for box in boxes:
    if not box.is_selected():
        box.click()

The equivalent Java loop is:

List<WebElement> boxes = driver.findElements(
    By.cssSelector("#preferences input[type='checkbox']")
);

for (WebElement box : boxes) {
    if (!box.isSelected()) {
        box.click();
    }
}

Use a locator that identifies the intended group. Selecting every input[type='checkbox'] on a page can change unrelated controls such as cookie preferences, navigation filters, or an “accept terms” box.

Choose a locator that survives page changes

Prefer IDs, names, and meaningful containers

A stable ID on the form or fieldset is usually the clearest option:

driver.find_elements(By.CSS_SELECTOR, "#notification-settings input[type='checkbox']")

You can also target a named group or a fieldset:

driver.find_elements(
    By.CSS_SELECTOR,
    "fieldset[name='languages'] input[type='checkbox']"
)

Use an element’s name, id, or a meaningful class/data attribute when those values are part of the application’s contract. Absolute XPath such as /html/body/div[2]/div[4]/input[3] is tied to the current layout and is likely to break when a wrapper is added.

Filter to a known subset

If the page contains several groups, scope first and then filter by a value or label-related attribute. For example:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
boxes = driver.find_elements(
    By.CSS_SELECTOR,
    "#interests input[type='checkbox'][name='interest']"
)

When a test needs only specific values, inspect each element’s value attribute before clicking:

wanted = {"python", "selenium", "testing"}

for box in boxes:
    if box.get_attribute("value") in wanted and not box.is_selected():
        box.click()

Do not assume the order returned by find_elements is a business rule. Select by an identifying attribute rather than by index whenever possible.

A complete Python example with explicit waits

Pages that render controls asynchronously need synchronization. The following example waits for the group to exist and for each checkbox to be usable, then verifies the result. It avoids a fixed sleep, which can be too short on a slow run and unnecessarily long on a fast one.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

URL = "https://example.com/preferences"
GROUP = (By.CSS_SELECTOR, "#preferences input[type='checkbox']")

options = webdriver.ChromeOptions()
# options.add_argument("--headless=new")  # enable in CI if required

driver = webdriver.Chrome(options=options)
wait = WebDriverWait(driver, 15)

try:
    driver.get(URL)

    # Wait until at least one intended checkbox is present.
    wait.until(EC.presence_of_all_elements_located(GROUP))
    boxes = driver.find_elements(*GROUP)

    for box in boxes:
        # Re-check visibility and enabled state at interaction time.
        wait.until(lambda d, element=box:
                   element.is_displayed() and element.is_enabled())
        if not box.is_selected():
            box.click()

    # Confirm every targeted box is selected.
    wait.until(lambda d: all(
        element.is_selected()
        for element in d.find_elements(*GROUP)
    ))
finally:
    driver.quit()

The final wait re-queries the group so the assertion reflects the current DOM. If the application redraws the controls after each click, use a fresh lookup inside the loop rather than retaining old element references (see the stale-element section below).

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Selecting an exact set, not simply checking everything

Make the target state explicit

Often the test should select a particular set and clear all other boxes. Build a set of desired values, then set each control to the required state:

wanted = {"email", "sms"}

for box in driver.find_elements(
    By.CSS_SELECTOR, "#contact-preferences input[type='checkbox']"
):
    should_be_selected = box.get_attribute("value") in wanted
    if box.is_selected() != should_be_selected:
        box.click()

This approach is also safe to run repeatedly: once the page matches the desired state, another run makes no changes.

Select only currently unchecked boxes

For a “check all” action, retain the simple state-aware loop:

for box in driver.find_elements(
    By.CSS_SELECTOR, "#preferences input[type='checkbox']"
):
    if not box.is_selected():
        box.click()

To select only unchecked boxes that meet another condition, combine the condition with the state check rather than clicking first and inspecting later.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When the visible control is not the native input

Modern interfaces frequently hide the native checkbox and render a styled button, label, or custom widget. Inspect the markup and determine which element is actually user-interactable and exposes the accessible checked state.

Label-driven markup

For markup such as <input id="news" type="checkbox"><label for="news">News</label>, clicking the label can be appropriate when the input is intentionally hidden:

label = driver.find_element(By.CSS_SELECTOR, "label[for='news']")
label.click()

Use the associated input to verify the result:

checkbox = driver.find_element(By.ID, "news")
assert checkbox.is_selected()

Custom ARIA widgets

A custom control may be a button with role="checkbox" and an aria-checked attribute. In that case, locate the accessible control, read its attribute, and click only when it reports false:

widget = driver.find_element(
    By.CSS_SELECTOR, "[role='checkbox'][data-name='alerts']"
)
if widget.get_attribute("aria-checked") != "true":
    widget.click()

Do not force a click on a hidden input merely because it is easy to locate. Selenium checks whether an element is interactable; a hidden or covered element can produce a non-interactable or intercepted-click error. The page’s accessible control is normally the correct target.

Waiting, scrolling, and verifying interactions

Wait for the condition the page needs

  • Use a presence wait when the elements must exist in the DOM.
  • Use visibility or an enabled check when the user must be able to interact with them.
  • After a click that triggers an update, wait for the resulting condition, such as a summary count, enabled submit button, or updated attribute.

Selenium scrolls an element into view as part of interaction, but a fixed header, animation, modal, or overlay can still cover the click point. If a click is intercepted, inspect what occupies the element’s center rather than adding an arbitrary delay.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Verify both state and outcome

For a pure checkbox test, assert is_selected() (or isSelected()) for every target. For an end-to-end test, also verify the behavior that matters: a selected filter appears, a total changes, or the submitted form contains the expected values. State verification catches a failed click before the test reaches a later, less informative assertion.

Dynamic pages and stale element references

Some frameworks replace the entire checkbox row after each click. The old WebElement then points to a node that no longer exists, and Selenium raises a stale-element reference error. Re-find the collection after each update:

selector = "#dynamic-list input[type='checkbox']"
index = 0

while True:
    boxes = driver.find_elements(By.CSS_SELECTOR, selector)
    if index >= len(boxes):
        break
    box = boxes[index]
    if not box.is_selected():
        box.click()
        WebDriverWait(driver, 10).until(
            lambda d: len(d.find_elements(By.CSS_SELECTOR, selector)) >= index + 1
        )
    index += 1

A value-based loop is usually better than an index when the order can change. After each click, locate the checkbox by its stable value or data attribute, then inspect and click the newly returned element.

Checkboxes are not multi-select dropdowns

Several independent <input type="checkbox"> controls are operated one at a time. A multi-select dropdown is a <select multiple> element, which is a different HTML control and has separate Selenium select-list support. Do not apply Selenium’s Select helper to an arbitrary group of checkboxes; locate and click the checkbox controls themselves.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Troubleshooting common failures

Symptom Likely cause Fix
No elements found The selector is wrong, the group has not rendered, or the locator is scoped to the wrong frame. Inspect the live markup, scope to the correct container, wait for presence, and switch to the relevant iframe when applicable.
Element click intercepted An overlay, cookie dialog, sticky header, or animation covers the click point. Dismiss the overlay through its normal control, wait for the animation to finish, scroll the element into a usable position, and retry.
Element not interactable The matched input is hidden, disabled, or replaced by a custom visual control. Locate the visible label or accessible widget, confirm it is enabled, and verify the native input’s state afterward.
Boxes become unchecked The loop clicks already-selected controls and toggles them off. Guard every click with not is_selected() or !isSelected().
Stale element reference The framework replaced the node after a click. Re-locate the checkbox after each DOM update and avoid retaining a collection across redraws.
Selection appears correct but submission is wrong The test selected a similarly named group or a custom widget did not update its underlying input. Assert the exact container, inspect submitted values or the resulting UI, and verify both the accessible state and native form state.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance and reliability considerations

For a normal group, one lookup followed by a short loop is efficient and readable. Avoid repeatedly searching the entire document when a stable container is available. If the page redraws after every click, correctness requires fresh lookups, but you can still narrow each lookup to the group.

  • Use explicit waits tied to DOM or application conditions instead of global implicit waits plus long sleeps.
  • Keep the desired state in data (for example, a set of values) so reruns are deterministic.
  • Capture useful diagnostics when a click fails: URL, checkbox attributes, visibility, enabled state, and a screenshot of the obstructing UI.
  • Run the same test against the browser versions your project supports; interactability can vary with responsive layout and viewport size.

Or skip the browser setup

If your goal is a clean page image rather than interactive checkbox testing, ScreenshotNeo provides a single HTTP request that returns a PNG, JPEG, WebP, or PDF. Its preprocessing accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Only clean shots are billed, while bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

See the ScreenshotNeo API documentation for parameters. A one-call cURL capture is:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

The same request in Python is:

import requests
r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)

And in Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Every plan includes features such as full-page capture with lazy images loaded, CSS-selector element capture, device and viewport choices, retina scale, PDF controls, custom CSS and JavaScript, click-before-capture, selector hiding, waits, request blocking, custom headers and cookies, timezone and geolocation, resizing, selectable-TTL caching, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage reporting, and an OpenAPI specification. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Frequently asked questions

Can Selenium select a checkbox by its label text?

Yes, when the label is associated with the input through for/id or wraps the input. Locate the label, click it when the input is hidden, and verify the associated input’s selected state.

What does is_selected() report for a radio button?

The method reports whether a supported selectable element, including a radio button, is selected. Radio buttons remain mutually exclusive, so the multi-checkbox loop should not be used to select several radios.

Why should a test verify the form result as well as the checkbox state?

A custom widget can display a checked style without updating the value submitted by the form. Checking the resulting filter, summary, or submitted data confirms that the user-visible action also produced the intended application behavior.

Frequently Asked Questions

Can Selenium select a checkbox by its label text?

Yes. Click an associated label when the native input is hidden, then verify the input’s selected state.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What does is_selected() report for a radio button?

It reports whether a supported selectable element is selected; radio buttons are mutually exclusive and are not a multi-checkbox group.

Why verify the form result as well as checkbox state?

A custom widget may look checked without updating submitted data, so assert the resulting application behavior too.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.