Question
How can I restrict which file formats a user can select in the native operating system file chooser opened by an HTML <input type="file"> element? I would like to use only HTML and JavaScript, without browser plugins such as Flash.
Short Answer
You will learn how the HTML accept attribute filters the file chooser, how to use file extensions and MIME types, and why client-side filtering is only a convenience rather than upload security. You will also see how to validate a selected file with JavaScript and why a server must still perform final validation.
Concept
The main HTML feature for suggesting allowed upload formats is the accept attribute on a file input.
<input type="file" accept=".png,.jpg,.jpeg">
When the user opens the browser's native file chooser, the browser passes this preference to the operating system. The chooser will usually show matching files first or limit its visible file filter to those formats.
However, accept is not a strict security restriction:
- Browser and operating system behavior varies.
- Many file choosers let users switch to an option such as All files.
- A user can rename a file to give it a different extension.
- A malicious user can bypass browser checks completely by sending a custom HTTP request.
Therefore, use accept to improve the user experience, use JavaScript to give immediate feedback, and validate files again on the server before storing or processing them. HTML and JavaScript alone cannot securely enforce an upload policy because the user controls the browser.
Mental Model
Think of accept as a sign at the entrance to a filing cabinet saying, “Please put image files here.” The sign helps a cooperative person find the right documents, but it is not a lock.
JavaScript is like a receptionist who checks the label when a document is handed over and can ask the person to choose another one. Server-side validation is the locked records room: it must inspect the document before accepting it, because it is the only part the user cannot alter.
Syntax and Examples
Use accept with one or more comma-separated file type specifiers.
Accept specific extensions
<label for="photo">Choose a photo:</label>
<input id="photo" name="photo" type="file" accept=".png,.jpg,.jpeg">
This asks the chooser to show PNG and JPEG files.
Accept MIME types
<input type="file" accept="image/png,image/jpeg">
MIME types describe the content category and format. Common examples include image/png, application/pdf, and text/csv.
Accept every type in a category
<input type="file" accept="image/*">
image/* requests any image type supported by the browser and operating system. Use explicit types when your application supports only particular formats.
Allow multiple files
<input type="file" accept=".pdf,.docx" multiple>
The multiple attribute changes the number of files a user may select; it does not change how accept works.
Add JavaScript feedback
<input id="resume" type="file" accept="application/pdf,.pdf">
<p id="message" role="alert"></p>
<script>
const input = document.querySelector("#resume");
const message = document.querySelector("#message");
input.addEventListener("change", () => {
const file = input.files[0];
if (!file) {
message.textContent = "";
return;
}
const isPdf = file.type === "application/pdf" ||
file.name.toLowerCase().endsWith(".pdf");
if (!isPdf) {
message.textContent = "Please choose a PDF file.";
input.value = "";
return;
}
message.textContent = `Selected: ${file.name}`;
});
</script>
input.files is a FileList containing the selected files. For a single-file input, the first selected file is input.files[0]. The example checks both the MIME type and extension because file.type can be empty or unreliable on some systems.
Step by Step Execution
Consider this example:
<input id="avatar" type="file" accept="image/png,image/jpeg">
<p id="status"></p>
<script>
const avatar = document.querySelector("#avatar");
const status = document.querySelector("#status");
avatar.addEventListener("change", () => {
const file = avatar.files[0];
if (!file) {
status.textContent = "No file selected.";
return;
}
if (file.type !== "image/png" && file.type !== "image/jpeg") {
status.textContent = "Choose a PNG or JPEG image.";
avatar.value = "";
return;
}
status.textContent = `${file.name} is ready to upload.`;
});
</script>
Execution when a user selects cat.png:
- The user clicks the input. The
acceptvalue tells the chooser to prefer PNG and JPEG files. - The user selects
cat.pngand closes the chooser. - The input fires its
changeevent. avatar.files[0]stores aFileobject representingcat.png.- The first
ifis skipped because a file exists. - The second
ifis skipped because its MIME type isimage/png. - The success message is displayed.
If the user selects a file reported as application/pdf, the second condition is true. The script displays an error and sets avatar.value to an empty string, which clears the selection.
Real World Use Cases
- Profile photo upload: Suggest JPEG, PNG, or WebP files with
accept="image/jpeg,image/png,image/webp". - Resume submission: Ask applicants for a PDF using
accept="application/pdf,.pdf". - Data import tool: Guide users toward CSV files with
accept=".csv,text/csv". - Document portal: Allow approved office formats such as PDF and DOCX.
- Media dashboard: Let content editors select audio or video formats supported by the application.
In each case, the chooser filter reduces accidental selection of unsupported files. The upload endpoint must still reject invalid, oversized, or unsafe files.
Real Codebase Usage
In real applications, developers usually combine three layers.
- Chooser guidance: Add
acceptto make the normal path easy for users. - Client-side validation: Check selected files before uploading so the UI can show immediate, friendly errors.
- Server-side validation: Enforce the actual policy before saving or processing data.
A reusable client-side validation function often checks both type and size:
function validateImage(file) {
const allowedTypes = new Set(["image/jpeg", "image/png"]);
const maximumBytes = 5 * 1024 * 1024;
if (!allowedTypes.has(file.type)) {
return "Choose a JPEG or PNG image.";
}
if (file.size > maximumBytes) {
return "The image must be 5 MB or smaller.";
}
return null;
}
A change handler can use a guard clause to stop as soon as a file is invalid:
const error = validateImage(file);
if (error) {
showError(error);
return;
}
uploadFile(file);
On the server, robust validation commonly includes a file-size limit, an allowlist of supported formats, inspection of file signatures or decoded content when appropriate, safe generated filenames, and storage outside publicly executable directories.
Common Mistakes
Treating accept as security
<input type="file" accept=".pdf">
This does not guarantee that only PDFs reach your server. It is a browser hint. Always validate uploads on the server.
Using only a filename extension in JavaScript
// Not enough by itself
if (file.name.endsWith(".png")) {
uploadFile(file);
}
A filename can be changed easily, such as renaming program.exe to photo.png. An extension check can improve feedback, but it cannot prove file content is safe or valid.
Trusting file.type completely
if (file.type === "image/png") {
uploadFile(file);
}
file.type is useful for UI validation, but it may be empty or based on operating-system file associations. Do not use it as your only security check.
Forgetting that the user can cancel
const file = input.files[0];
console.log(file.name); // Can fail if no file exists
Check that file exists before accessing its properties.
const file = input.files[0];
if (!file) return;
console.log(file.name);
Assuming every chooser enforces the filter identically
Different browsers and operating systems present file filters differently. Design your form so it remains understandable even if a user selects an unsupported file.
Using a nonstandard attribute
Attributes such as filetype, extensions, or filter are not standard HTML file-input restrictions. Use the standard accept attribute.
Comparisons
| Technique | Where it runs | What it does | Security value |
|---|---|---|---|
accept attribute | Browser file chooser | Suggests or filters selectable file formats | None by itself |
| JavaScript validation | Browser after selection | Gives immediate feedback and can prevent normal UI submission | Easily bypassed |
| Server-side validation | Server upload endpoint | Enforces allowed type, size, and processing rules | Required |
| Extension check | Browser or server | Checks the filename suffix, such as .pdf | Weak; names can be changed |
| MIME type check | Browser or server | Checks a declared or detected media type | Useful, but should be verified server-side |
Explicit formats vs wildcard formats
| Value | Best for | Example |
|---|---|---|
| Explicit extensions | A small known set of file names | .jpg,.jpeg,.png |
| Explicit MIME types | A small known set of media formats | image/jpeg,image/png |
| Category wildcard | Any format in a broad category | image/* |
Prefer explicit formats when your application can process only specific formats.
Cheat Sheet
<!-- One extension -->
<input type="file" accept=".pdf">
<!-- Several extensions -->
<input type="file" accept=".png,.jpg,.jpeg">
<!-- MIME types -->
<input type="file" accept="image/png,image/jpeg">
<!-- Broad category -->
<input type="file" accept="image/*">
<!-- More than one file -->
<input type="file" accept=".csv,text/csv" multiple>
- Separate accepted values with commas.
- Use extensions, MIME types, or a category wildcard such as
image/*. - Read selected files from
input.files. - For one file, use
input.files[0]after checking it exists. - Use JavaScript for fast user feedback.
acceptand JavaScript validation can be bypassed.- Enforce type, size, and safety rules on the server.
FAQ
Can HTML completely prevent users from choosing another file type?
No. The accept attribute asks the browser and operating system to filter or suggest files, but users may be able to choose an all-files option or bypass the page entirely.
What is the correct attribute for restricting a file input?
Use accept, for example: <input type="file" accept=".pdf">.
Should I use file extensions or MIME types in accept?
You can use either, and including both is often practical. For example: accept="application/pdf,.pdf".
Does accept="image/*" allow every image format?
It requests image formats recognized by the browser and operating system. It does not guarantee that your application or server can process every possible image format.
Can JavaScript determine the real file type securely?
Not securely enough to protect an upload endpoint. JavaScript checks are helpful for user experience, but the server must validate the uploaded bytes and enforce its policy.
How do I clear an invalid file selection in JavaScript?
Assign an empty string to the input value:
input.value = "";
Why is file.type empty for some files?
The browser may not know a MIME type for the file, or the operating system may not provide one. Handle an empty type as untrusted or unsupported in client-side validation.
Does multiple restrict file formats?
No. multiple only permits selecting more than one file. Combine it with accept when needed.
Mini Project
Description
Build a small image-upload picker for a profile settings page. It guides users toward PNG or JPEG images, checks the selected file in the browser, and displays either a helpful error or a success message. This mirrors the client-side portion of a real upload form.
Goal
Create a file input that accepts JPEG and PNG images up to 2 MB and reports whether the chosen file is ready for upload.
Requirements
Use an <input type="file"> with an accept attribute for PNG and JPEG files.
Add a message area that reports validation results.
Reject files that are not PNG or JPEG images.
Reject files larger than 2 MB.
Clear the file input when validation fails.
Keep learning
Related questions
Add a Favicon to a Static HTML Page
Learn how to add a favicon to static HTML pages, use correct paths and icon formats, and troubleshoot browser caching and local-file issues.
Allow Only Numeric Input (0-9) in HTML Input Using jQuery
Learn how to allow only digits 0-9 in an HTML input using jQuery, with examples, validation tips, common mistakes, and best practices.
Apply CSS !important with jQuery .css()
Learn why jQuery .css() cannot set !important and how to use CSSStyleDeclaration.setProperty() to apply inline important styles safely.