October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk5 min

How to Upload Images with JavaScript

Use a file input and FormData to POST an image with fetch(), or submit it through a native multipart form. Learn the key server, CORS, and validation pitfalls.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To upload an image from a web page, let the user choose it with an <input type="file">, put the selected file in a FormData object, and send it to an application endpoint with fetch(). The endpoint—not browser JavaScript—must parse the multipart request, validate the file, and decide how to store or process it. If a full-page form submission is acceptable, a native HTML form can do the upload without JavaScript.

Choose a native form or a JavaScript upload

Approach What happens Best fit
Native HTML form The browser submits the form and handles the response as a page navigation. Minimal client code when a full-page response is fine.
JavaScript with fetch() Your handler intercepts submission and sends the form without navigating away, so the page can update its own status UI. When the page should remain in place or needs custom submission behavior.

Both approaches require a server route that accepts multipart/form-data. See MDN’s guides to sending form data and sending forms through JavaScript.

Build the file input

The browser-mediated file picker exposes the selected file or files through the input’s files property. Use the File object for the upload; the input’s string value is not the file data. Give the control a name that matches the key expected by your endpoint.

<form id="image-form">
  <label for="image">Choose an image</label>
  <input id="image" name="image" type="file" accept="image/*" required>
  <button type="submit">Upload</button>
  <p id="status" role="status"></p>
</form>

accept="image/*" guides the picker but does not enforce the file type. You can use narrower hints such as accept=".jpg,.jpeg,.png"; either way, validate the actual content on the server. The file input reference documents the picker and its files property; MDN’s accept attribute reference explains that it is only a hint.

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

Upload with JavaScript and fetch()

This example constructs FormData from the form, posts it to /uploads, and checks the HTTP response before displaying success. Replace /uploads with your actual route and make sure its multipart parser expects the field name image.

const form = document.querySelector("#image-form");
const status = document.querySelector("#status");

form.addEventListener("submit", async (event) => {
  event.preventDefault();

  const fileInput = form.elements.image;
  const file = fileInput.files[0];
  if (!file) {
    status.textContent = "Choose an image first.";
    return;
  }

  const formData = new FormData(form);

  try {
    const response = await fetch("/uploads", {
      method: "POST",
      body: formData,
    });

    if (!response.ok) {
      throw new Error(`Upload failed: ${response.status}`);
    }

    status.textContent = "Upload complete.";
  } catch (error) {
    status.textContent = "Upload failed. Please try again.";
    console.error(error);
  }
});

Fetch resolves to a Response even when the server returns an HTTP error status, so check response.ok. Parse a response with response.json() only if your endpoint actually returns JSON. The multipart construction follows MDN’s guide to using FormData objects; endpoint routes and response formats are application-specific. For more on response handling, see MDN’s Fetch API guide.

Use a native form when JavaScript is unnecessary

If navigation after submission is acceptable, set the form’s method and encoding and let the browser submit it:

<form action="/uploads" method="post" enctype="multipart/form-data">
  <label for="image-native">Choose an image</label>
  <input id="image-native" name="image" type="file" accept="image/*" required>
  <button type="submit">Upload</button>
</form>

The action must point to a server endpoint that accepts multipart form data. Multipart encoding allows the request to include the file alongside ordinary form fields.

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

Handle multiple files only when the endpoint supports them

Add multiple when users should be able to choose more than one image. The files property is a FileList, so process each selected file, and align the field structure with what the server parser expects. The server may be designed for repeated fields or another multiple-file convention; do not assume it accepts multiple files just because the input does.

<input id="images" name="images" type="file" accept="image/*" multiple>

const files = document.querySelector("#images").files;
const formData = new FormData();
for (const file of files) {
  formData.append("images", file);
}

Keep multipart headers and server responsibilities straight

  • Do not set the multipart Content-Type yourself. When FormData is the fetch body, the browser adds the required boundary parameter. Setting only Content-Type: multipart/form-data can leave out the boundary the server needs to separate parts.
  • Validate on the server. Treat files and their client-supplied names, MIME types, and sizes as untrusted. Browser-side checks can improve feedback, but the server must enforce allowed content and size limits and apply the application’s storage and security rules.
  • Match field names. A form-derived FormData uses control names as keys. If the input has no name, or its name differs from the parser’s expected key, the server may appear to receive no file.
  • Account for cross-origin rules. The server must configure CORS so the browser can expose the response to JavaScript; some requests also trigger a preflight. mode: "no-cors" does not solve response access: it produces an opaque response whose body and headers are hidden from JavaScript.
  • Use the server’s real size limits. Browser APIs establish no universal maximum upload size. The application and its deployment determine applicable limits.

Troubleshoot common upload failures

Symptom Likely cause What to check
The server reports no file The input lacks a name, the name differs from the server parser’s expected field, or the endpoint does not parse multipart data. Inspect the submitted form field name and confirm the route accepts multipart/form-data.
Multipart parsing fails A manually supplied Content-Type omitted the browser-generated boundary. Remove the Content-Type header when sending a FormData body.
The UI says upload succeeded for an error response The code treated fetch resolution as proof of success. Check response.ok or the status code before showing success.
JavaScript cannot read a cross-origin response The server’s CORS configuration does not permit access, or the request needs a preflight that is not handled. Configure CORS on the endpoint. Do not use no-cors if the page needs to inspect the response.
A file type or size check is bypassed accept or other client-side metadata was treated as security enforcement. Enforce type and size rules at the server using the application’s upload policy.
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 capturing a website image rather than uploading a file selected by a visitor, ScreenshotNeo is a screenshot API and MCP server for developers. One GET request returns a PNG, JPEG, WebP, or PDF. For example, the cURL request below saves a WebP screenshot; create an API key and see the API documentation for request options.

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

ScreenshotNeo accepts cookie/consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; those steps can be turned off. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots.

Sign up for 1,000 free screenshots a month, with no card required.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

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

More from the Wire

  1. Shenzhen desk3 min
    HONOR Expands Beyond Smartphones With Humanoid Robot RevealHONOR said it unveiled its first humanoid robot at MWC 2026 and named shopping assistance, workplace inspections, and supportive companionship as intended uses. Later Robotics D1 claims and a reported…
  2. Cupertino desk5 min
    Apple Unveils AirPods Max 2: The Upgrade That Should Have Happened Years AgoAirPods Max 2 adds H2-powered audio features and Apple claims up to 1.5× more effective ANC, but its design, Smart Case, and 20-hour battery rating are unchanged. Wired lossless audio…
  3. Cupertino desk4 min
    Apple’s OLED Touch MacBooks Are Coming—but the Dynamic Island Is the Real GambleApple has not announced an OLED touchscreen MacBook, but reports point to high-end models arriving in late 2026 or early 2027. The reported Mac Dynamic Island could be useful, but…
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.