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.

The reliable way to select a date with Selenium Java depends on the control you are testing. For a native <input type="date">, enter the normalized yyyy-MM-dd value and assert the element’s value. For a custom calendar, open the widget, navigate its month and year controls, click the correct day, and verify the resulting field or application state. Inspect the rendered HTML before choosing either strategy.

First identify which date picker you have

Selenium has no universal “select date” command because date pickers are implemented in two materially different ways.

  • Native date input: the browser and operating system provide the picker UI for an <input type="date">. The visible format can vary with locale, but the stored value is normalized.
  • Custom calendar: the page supplies its own HTML, CSS and JavaScript. Its trigger, month heading, navigation buttons and day elements are specific to that application or widget library.

Use browser developer tools to inspect the field and surrounding markup. Check the element’s type, stable attributes, editability, current value, and any min or max constraints. For a custom widget, identify the calendar container, month/year label, previous/next controls and the day buttons or cells.

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

Selecting a native HTML date input

Use the normalized value, not the localized display

Native date controls store dates as yyyy-mm-dd, even when the browser displays them in another order. A test should therefore assert the value property rather than text seen in a screenshot. A date outside the element’s min or max range is invalid even if it can be typed.

Complete Java example

import static org.junit.jupiter.api.Assertions.assertEquals;
import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.WebDriverWait;

class NativeDateTest {
  @Test
  void selectsDate() {
    WebDriver driver = new ChromeDriver();
    try {
      driver.get("https://example.test/booking");
      WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
      WebElement date = wait.until(d -> d.findElement(By.id("startDate")));

      // Choose a value allowed by this page's min/max attributes.
      date.clear();
      date.sendKeys("2026-10-15");

      assertEquals("2026-10-15", date.getAttribute("value"));
    } finally {
      driver.quit();
    }
  }
}

Use a stable ID, name, or label relationship instead of a generated class name. sendKeys is appropriate only when the element is displayed and keyboard-interactable. WebDriver checks interactability; a hidden or non-editable element can produce an element-not-interactable error. If the page visually shows a calendar but the editable element is a separate input, locate and operate the actual input.

When direct entry is rejected

Some implementations expose a read-only field or intercept keyboard input. Inspect which element receives user input, then use the browser-supported interaction for that element. Do not assume that assigning a DOM value with JavaScript is equivalent to a user action: application listeners and validation may depend on real input and change events. After any interaction, assert the value and, when relevant, the form’s validation state.

Selecting a custom calendar widget

Map the widget before writing locators

Open the trigger manually and inspect the rendered DOM. Record selectors for:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • the input or button that opens the calendar;
  • the visible month/year heading;
  • previous and next month (or year) controls;
  • day buttons or cells, including attributes that mark the current month, disabled days and selected days.

Day numbers often appear twice because leading and trailing days from adjacent months are rendered in the same grid. A locator that matches only “15” can select the wrong month. Prefer a widget-specific container plus a current-month marker, an accessible date label, or a data attribute containing the full date.

Navigate by the widget’s observable state

Click the trigger, wait for the calendar to be visible, read the heading, and click next or previous until the required month is shown. Then click the day that belongs to that month. Use explicit waits for visibility or clickability rather than fixed sleeps.

import static org.junit.jupiter.api.Assertions.assertEquals;
import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

class CustomCalendarTest {
  @Test
  void selectsCalendarDate() {
    WebDriver driver = new ChromeDriver();
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    try {
      driver.get("https://example.test/booking");
      wait.until(ExpectedConditions.elementToBeClickable(By.id("date-trigger"))).click();
      wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".calendar")));

      // These selectors are examples: replace them with this widget's real markup.
      By heading = By.cssSelector(".calendar .month-year");
      By next = By.cssSelector(".calendar button.next");
      String wantedMonth = "October 2026";
      for (int i = 0; i < 24; i++) {
        String shown = driver.findElement(heading).getText();
        if (wantedMonth.equals(shown)) break;
        driver.findElement(next).click();
        wait.until(d -> wantedMonth.equals(d.findElement(heading).getText()));
      }

      By day = By.cssSelector(
          ".calendar [data-date='2026-10-15']:not([aria-disabled='true'])");
      wait.until(ExpectedConditions.elementToBeClickable(day)).click();
      assertEquals("2026-10-15",
          driver.findElement(By.id("date-input")).getAttribute("value"));
    } finally {
      driver.quit();
    }
  }
}

The loop limit is a safety guard; fail the test if the heading never reaches the target instead of silently selecting another month. If the widget changes the heading asynchronously, the wait condition should observe that change. When a full-date attribute is unavailable, combine the calendar container, month heading and day text, and exclude elements marked outside the current month or disabled.

Keyboard and accessibility paths

Selenium’s Actions API can send keys to a designated element. Use it when the widget documents keyboard navigation (for example, arrow keys followed by Enter). The supported keys are widget-specific, so inspect focus behavior and verify the resulting value. Clicking the real control is preferable to a JavaScript click that bypasses event sequencing, focus and accessibility behavior.

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

Waits, assertions and constraints

  • Wait for the input or trigger to be present and interactable.
  • Wait for the calendar to become visible after opening it.
  • After each month navigation, wait for the heading or date grid to update.
  • Assert the field’s canonical value, not merely that a click completed.
  • For booking or search forms, submit through the visible submit button and assert the resulting validation message, URL or application state.

Read min and max before choosing test data. Also account for disabled holidays, weekends, blackout ranges and dates that the application rejects after selection.

Common failures and precise fixes

ElementNotInteractableException

The element is hidden, disabled, read-only or not keyboard-interactable. Locate the visible input or trigger, wait for it to be clickable, and check overlays and disabled attributes. Do not repeatedly add delays.

The wrong day is selected

Adjacent-month days or duplicate calendars matched your locator. Scope the locator to the open widget and require the current-month marker or a full date attribute.

The month loop never finishes

The heading format, locale or navigation direction differs from your assumption. Log the heading, compare a normalized representation, and stop with a useful assertion failure after a bounded number of clicks.

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

The field looks correct but the form rejects it

The value may violate min/max, a disabled date rule, or a required change event. Read the value, inspect validation properties, and complete the interaction through the real control rather than assigning JavaScript properties.

StaleElementReferenceException after navigation

Many calendars rebuild their day grid. Re-find the heading or day element after each navigation instead of retaining references to replaced nodes.

Performance and reliability choices

Native inputs are usually the shortest and least fragile path because they avoid calendar navigation. Custom widgets require more DOM-specific code but exercise the same path a user follows. Keep locators semantic, isolate a page-object method for date selection, and use deterministic dates inside the page’s allowed range. Run tests in the browser/locale combinations your product supports because native display and custom labels can vary.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your goal is a rendered image or PDF rather than an interaction test, ScreenshotNeo provides a single screenshot request. It can accept consent banners before capture and remove more than 60 known consent platforms, newsletter popups and chat widgets; each step can be disabled. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients. The free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for options such as full-page capture, CSS-selector element capture, device and retina settings, PDF page ranges, custom JavaScript, waits, request blocking, cookies, headers, geolocation, caching, signed links, asynchronous webhooks and bulk capture.

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)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.

FAQ

Should I click a native calendar day instead of using sendKeys?

Use the editable date input when it accepts keyboard entry, then assert its normalized value. Click the native picker only when the field is not directly editable.

Can one XPath work for every date picker?

No. Custom calendars expose different markup, labels and state attributes. Build locators from the actual widget DOM.

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.

Why should tests assert yyyy-MM-dd?

That is the normalized value defined for native date inputs; the visual format is locale-dependent.

Frequently Asked Questions

Should I click a native calendar day instead of using sendKeys?

Use the editable date input when it accepts keyboard entry, then assert its normalized value. Click the native picker only when the field is not directly editable.

Can one XPath work for every date picker?

No. Custom calendars expose different markup, labels and state attributes. Build locators from the actual widget DOM.

Why should tests assert yyyy-MM-dd?

That is the normalized value defined for native date inputs; the visual format is locale-dependent.

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

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.