HTML
file input
capture attribute
accept attribute
web development

HTML file input control with capture and accept attributes works wrong?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

The accept and capture attributes on an HTML file input are often misunderstood because they look stronger than they really are. In practice, accept is a hint about preferred file types, and capture is a hint about which capture device a mobile browser may offer.

What accept Actually Does

accept helps the browser filter visible choices in the picker. It does not guarantee that the selected file is valid, and it does not replace server-side validation.

html
1<!doctype html>
2<html lang="en">
3  <body>
4    <label for="photo">Upload a photo</label>
5    <input id="photo" type="file" accept="image/*" />
6  </body>
7</html>

With accept="image/*", many browsers show image files first or restrict the picker UI to image sources. A user can still bypass this on some platforms, and even when the picker is filtered, the uploaded file must still be validated after selection.

What capture Actually Does

capture is mainly relevant on mobile devices. It asks the browser to prefer a camera, microphone, or similar capture source when the accepted media type supports it.

html
1<!doctype html>
2<html lang="en">
3  <body>
4    <label for="cameraInput">Take a picture</label>
5    <input
6      id="cameraInput"
7      type="file"
8      accept="image/*"
9      capture="environment"
10    />
11  </body>
12</html>

Common values are user for the front-facing camera and environment for the rear camera. Even then, browsers are free to ignore the preference. Some open the camera directly, some show a chooser, and some ignore capture entirely.

Why It Seems to Work Wrong

Most "wrong behavior" reports come from expecting strict guarantees. The browser is not required to enforce the exact flow you imagined.

These are common outcomes:

  • Desktop browsers often ignore capture.
  • Mobile browsers may interpret capture differently.
  • 'accept may filter the chooser but still allow unsupported files through other paths.'
  • Some operating systems merge camera capture and file selection into one UI, so it appears that capture had no effect.

That means the real contract is advisory, not mandatory.

A Practical Pattern

Use accept and capture to improve the user experience, then validate the file yourself in JavaScript and on the server.

html
1<!doctype html>
2<html lang="en">
3  <body>
4    <input id="avatar" type="file" accept="image/png,image/jpeg" capture="user" />
5    <p id="message"></p>
6
7    <script>
8      const input = document.getElementById("avatar");
9      const message = document.getElementById("message");
10
11      input.addEventListener("change", () => {
12        const file = input.files && input.files[0];
13
14        if (!file) {
15          message.textContent = "No file selected.";
16          return;
17        }
18
19        const allowedTypes = ["image/png", "image/jpeg"];
20        if (!allowedTypes.includes(file.type)) {
21          message.textContent = "Please choose a PNG or JPEG image.";
22          input.value = "";
23          return;
24        }
25
26        if (file.size > 2 * 1024 * 1024) {
27          message.textContent = "File must be 2 MB or smaller.";
28          input.value = "";
29          return;
30        }
31
32        message.textContent = `Selected: ${file.name}`;
33      });
34    </script>
35  </body>
36</html>

This pattern accepts the reality of browser differences. You provide hints, then enforce the rules yourself.

Designing for Cross-Device Behavior

If the main goal is "take a photo now," a file input can be good enough for many mobile web apps, but you should still test on your target devices. If you need tighter control over capture flow, preview, permissions, and retakes, browser media APIs may be more appropriate than relying only on the file input picker.

For example, a custom camera flow can use getUserMedia, show a live preview, and then convert a captured frame to a file-like blob. That is more work, but it removes some ambiguity in browser picker behavior.

javascript
1async function startCamera(videoElement) {
2  const stream = await navigator.mediaDevices.getUserMedia({
3    video: { facingMode: "environment" }
4  });
5
6  videoElement.srcObject = stream;
7  await videoElement.play();
8}

This approach does not replace upload validation, but it gives you a more controlled capture experience.

Common Pitfalls

  • Treating accept as security. It is only a hint; always validate type and size in application code and on the server.
  • Expecting capture to behave identically on iOS, Android, and desktop. Browser and operating system integration differs.
  • Forgetting that MIME types can be unreliable. Some files report empty or misleading file.type, so server validation is still essential.
  • Using capture without a compatible accept value. Asking for camera capture while accepting arbitrary files produces inconsistent results.

Summary

  • 'accept suggests which file types the picker should prefer.'
  • 'capture suggests a media capture source, mainly on mobile devices.'
  • Neither attribute guarantees identical behavior across browsers.
  • Client-side and server-side validation are still required.
  • Use media APIs when you need stricter control than the default file picker can provide.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.