<input type="date"> displays the date. The browser picks dd/mm/yyyy or mm/dd/yyyy from the user's browser and OS locale, and HTML has no format attribute. The submitted value and .value are always yyyy-mm-dd. Set today with new Date().toLocaleDateString("en-CA"), show a dd/mm/yyyy copy with Intl.DateTimeFormat("en-GB"), and only switch to a text input or a picker library when the format really must be fixed.Point any HTML form at one endpoint. 500 free submissions — no card, no time limit — and unlimited forms.
Create free accountCan you change the display format? You can't
This is the most common question about the HTML date input, and the honest answer is short: you can't. There is no format attribute, no CSS property and no JavaScript option that changes how the browser shows the date inside the field.
The browser decides the display format from the user's locale. Depending on the browser, that is the browser's UI language or the operating system's region settings. The same page shows:
- 11/04/2026 (mm/dd/yyyy) for a visitor with an en-US locale
- 04/11/2026 (dd/mm/yyyy) for en-GB, en-AU, en-IN and most of Europe
- 2026-11-04 for en-CA, Sweden and other yyyy-mm-dd locales
- 04.11.2026 for German
This is on purpose. A visitor in London reads 04/11 as 4 November, and one in New York reads it as 11 April. Letting the browser show each person their own format removes that confusion. If you test the page and see mm/dd/yyyy when you expected dd/mm/yyyy, check your own browser language and OS region, not your code.
The value is always yyyy-mm-dd
Whatever the user sees, the value is always in one fixed format: yyyy-mm-dd, the RFC 3339 full-date (the ISO 8601 calendar date). That is the format of input.value, of the value attribute, and of what the form sends:
<form action="https://splitforms.com/api/submit" method="POST">
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<label for="start">Start date</label>
<input id="start" name="start_date" type="date" required />
<button type="submit">Send</button>
</form>A user in the UK picks 4 November 2026 and sees 04/11/2026. The POST body still contains:
access_key=YOUR_ACCESS_KEY&start_date=2026-11-04This is good news for your backend: you never have to guess whether 04/11 means April or November. An empty, optional date field sends start_date= (an empty string). The same rule applies to input type="datetime-local", which sends yyyy-mm-ddThh:mm, such as 2026-11-04T14:30.
With the form above posting to splitforms, the date lands in your dashboard and email exactly as 2026-11-04. Get a free access key to try it.
Set today as the default value
The value attribute takes a fixed yyyy-mm-dd string, so a hard-coded default is easy: <input type="date" value="2026-11-04">. For "today", you need JavaScript, and the obvious version has a bug:
// Looks right, but uses the UTC date
input.valueAsDate = new Date();valueAsDate reads the date in UTC, not in the visitor's time zone. At 8 pm on 4 November in Los Angeles (UTC-8), it is already 5 November in UTC, so the field shows tomorrow. In Sydney at 9 am it is still the previous day in UTC, so the field shows yesterday. The same problem hits new Date().toISOString().slice(0, 10).
The safer one-liner formats the local date with a locale whose short date is already yyyy-mm-dd:
// Local date as yyyy-mm-dd, e.g. "2026-11-04"
input.value = new Date().toLocaleDateString("en-CA");If you prefer not to rely on a locale's format, build the string from the local parts:
function todayLocal() {
const d = new Date();
const mm = String(d.getMonth() + 1).padStart(2, "0");
const dd = String(d.getDate()).padStart(2, "0");
return d.getFullYear() + "-" + mm + "-" + dd;
}
input.value = todayLocal();min and max use yyyy-mm-dd too
The min and max attributes take the same format as the value. Dates outside the range are greyed out in most pickers and fail validation on submit:
<!-- Only dates in 2026 -->
<input type="date" name="event_date" min="2026-01-01" max="2026-12-31" />
<!-- No past dates: set min to today, in local time -->
<input type="date" name="booking_date" id="booking" />
<script>
document.getElementById("booking").min =
new Date().toLocaleDateString("en-CA");
</script>A min written as 01/01/2026 is not a valid date string, so the browser ignores it and applies no limit. Always check the range on the server as well, because anyone can send a request without a browser.
Show dd/mm/yyyy next to the field
If your audience expects one format, for example on a UK-only booking form, keep the native input and show a confirmation line in your format next to it. Intl.DateTimeFormat("en-GB") gives dd/mm/yyyy:
<label for="dob">Date of birth</label>
<input id="dob" name="dob" type="date" />
<p id="dob-text" aria-live="polite"></p>
<script>
const input = document.getElementById("dob");
const out = document.getElementById("dob-text");
const fmt = new Intl.DateTimeFormat("en-GB", { timeZone: "UTC" });
input.addEventListener("change", () => {
out.textContent = input.value
? "You picked " + fmt.format(new Date(input.value)) // "04/11/2026"
: "";
});
</script>timeZone: "UTC" matters: new Date("2026-11-04") is midnight UTC, and formatting it in a time zone west of UTC would show 03/11/2026. For an unambiguous line, use { dateStyle: "long" } instead, which prints "4 November 2026".
When you really need a fixed format
Sometimes the native picker is not an option: a design that must look the same everywhere, or users who type dates faster than they pick them. You have two choices.
1. A text input with a pattern
<label for="dob">Date of birth (dd/mm/yyyy)</label>
<input id="dob" name="dob" type="text"
inputmode="numeric"
pattern="\d{2}/\d{2}/\d{4}"
placeholder="dd/mm/yyyy"
autocomplete="bday" />inputmode="numeric" opens the number keypad on phones. Many of those keypads have no slash key, so either insert the slashes from JavaScript as the user types or tell users how to enter them. The pattern only checks the shape, so 31/02/2026 still passes. For patterns that also check day and month ranges or leap years, test one in the date regex tester. With a text input, the server receives the string exactly as typed, so it must parse dd/mm/yyyy itself.
2. A picker library
A library such as flatpickr gives you a picker that looks the same in every browser and shows any format, while still submitting yyyy-mm-dd. altInput adds a visible input in altFormat and keeps the real value in dateFormat:
<input id="date" name="date" type="text" />
<script>
flatpickr("#date", {
dateFormat: "Y-m-d", // submitted: 2026-11-04
altInput: true,
altFormat: "d/m/Y", // shown: 04/11/2026
});
</script>The trade-off is weight and accessibility. The native date input works with screen readers and the phone's own picker for free. Test a library with a keyboard and a screen reader before you ship it.
Reading the date in JavaScript: value vs valueAsDate vs valueAsNumber
A date input gives you three ways to read the same date:
input.value: the string"2026-11-04", or""when empty. Best for sending and storing.input.valueAsDate: aDateat midnight UTC on that day, ornullwhen empty. Read it with thegetUTC*methods.input.valueAsNumber: milliseconds since 1 January 1970 UTC for that midnight, orNaNwhen empty. Handy for comparing two dates.
const start = document.querySelector("#start");
const end = document.querySelector("#end");
start.value; // "2026-11-04"
start.valueAsDate; // Date: 2026-11-04T00:00:00.000Z
start.valueAsNumber; // 1793750400000
// Number of nights between two dates
const nights = (end.valueAsNumber - start.valueAsNumber) / 86400000;
// Local Date for the same calendar day (no UTC shift)
const [y, m, d] = start.value.split("-").map(Number);
const local = new Date(y, m - 1, d);Parsing the date on the server
Because the browser always sends yyyy-mm-dd, the server can parse one strict format. Still validate it: a request can come from anywhere.
Node.js
function parseDate(s) {
if (!/^\d{4}-\d{2}-\d{2}$/.test(s)) return null;
const [y, m, d] = s.split("-").map(Number);
const date = new Date(Date.UTC(y, m - 1, d));
// Rejects 2026-02-31, which Date would roll over to March
return date.getUTCMonth() === m - 1 && date.getUTCDate() === d ? date : null;
}PHP
$date = date_create_from_format('!Y-m-d', $_POST['start_date'] ?? '');
if ($date === false || $date->format('Y-m-d') !== $_POST['start_date']) {
// invalid date
}
echo $date->format('d/m/Y'); // 04/11/2026The ! resets the time to midnight. The round-trip check catches dates like 2026-02-31 that PHP would otherwise roll over.
Python
from datetime import date
try:
d = date.fromisoformat(form["start_date"]) # date(2026, 11, 4)
except ValueError:
d = None # empty or invalid
print(d.strftime("%d/%m/%Y")) # 04/11/2026React: a controlled date input
In React, keep the yyyy-mm-dd string in state. Don't store a Date object in value; the input needs the string:
import { useState } from "react";
const today = () => new Date().toLocaleDateString("en-CA");
const fmt = new Intl.DateTimeFormat("en-GB", { timeZone: "UTC" });
export function StartDate() {
const [date, setDate] = useState(today);
return (
<label>
Start date
<input
type="date"
name="start_date"
min={today()}
value={date}
onChange={(e) => setDate(e.target.value)}
/>
{date && <small>{fmt.format(new Date(date))}</small>}
</label>
);
}e.target.value is "" while the user is part-way through typing an invalid date, so always handle the empty string.
FAQ
How do I change the format of input type=date to dd/mm/yyyy?
You can't. The browser shows the date in the format of the user's browser and operating system locale, and HTML has no format attribute. A visitor with an en-GB locale sees dd/mm/yyyy and a visitor with en-US sees mm/dd/yyyy on the same page. Show a formatted copy next to the field with Intl.DateTimeFormat, or use a text input or a picker library when the display format must be fixed.
What format does input type=date submit?
Always yyyy-mm-dd, such as 2026-11-04. This is the RFC 3339 full-date (the ISO 8601 calendar date). The input's .value uses the same format, whatever the user sees on screen. An empty field submits an empty string.
How do I set input type=date to today by default?
Use the local date: input.value = new Date().toLocaleDateString("en-CA"), which gives yyyy-mm-dd in the visitor's time zone. Avoid input.valueAsDate = new Date(): it uses the UTC date, so in the evening west of UTC (or the early morning east of UTC) the field shows the wrong day.
What format do min and max use on a date input?
The same yyyy-mm-dd format as the value, for example min="2026-01-01" max="2026-12-31". A different format, such as 01/01/2026, is ignored. Dates outside the range fail validation when the form is submitted.
Why does my date input show one day earlier?
Something read the date as midnight UTC and then formatted it in a time zone west of UTC. new Date("2026-11-04") and input.valueAsDate are both midnight UTC. Pass timeZone: "UTC" to Intl.DateTimeFormat, or build the date from its parts with new Date(y, m - 1, d).
Can I use a placeholder like dd/mm/yyyy on input type=date?
No. placeholder does not apply to date inputs, and the browser shows its own format hint in the user's locale. Put any hint in the label or in help text below the field.
References: MDN: input type="date", RFC 3339 section 5.6 and flatpickr options.