By framework · React

File upload API for React, in 12 lines

Plain fetch + FormData. No SDK, no S3 buckets, no signed URLs. POST a file, get a permanent CDN URL back. Works in Vite, CRA, Remix, anywhere React runs.

Get free API key 300 uploads / mo free · no credit card
async function upload(file) {
  const fd = new FormData();
  fd.append('file', file);
  const r = await fetch('https://filepost.dev/v1/upload', {
    method: 'POST',
    headers: { 'X-API-Key': import.meta.env.VITE_FILEPOST_KEY },
    body: fd,
  });
  return (await r.json()).url; // permanent CDN URL
}

The full React component

Drop this into any Vite or CRA app. It uploads on file-select and shows the resulting URL.

import { useState } from 'react';

export default function FileUploader() {
  const [url, setUrl] = useState(null);
  const [loading, setLoading] = useState(false);

  async function onChange(e) {
    const file = e.target.files?.[0];
    if (!file) return;
    setLoading(true);
    const fd = new FormData();
    fd.append('file', file);
    const r = await fetch('https://filepost.dev/v1/upload', {
      method: 'POST',
      headers: { 'X-API-Key': import.meta.env.VITE_FILEPOST_KEY },
      body: fd,
    });
    const data = await r.json();
    setUrl(data.url);
    setLoading(false);
  }

  return (
    <div>
      <input type="file" onChange={onChange} disabled={loading} />
      {url && <a href={url}>{url}</a>}
    </div>
  );
}

That's the whole upload flow. 27 lines including the JSX. No backend, no IAM, no CDN distribution to wait three days to provision.

FilePost vs S3 + presigned URLs vs uploadthing — for React specifically

What you do FilePost S3 + presigned URL uploadthing
Lines of React code~12~40 (plus a Lambda for signing)~30 (provider + hook)
Backend requiredNoYes (signing endpoint)Yes (Next.js API route)
Permanent URLYesNo (object key, not URL)Yes
CORS config neededNoYes (bucket policy)No
Time-to-first-upload~20 min2–4 hours~30 min (Next.js only)
Free tier300 / mo, no card5 GB / 20k requests, no card2 GB total, no card
Paid plan starts$9 / mo~$0.023 / GB stored$10 / mo
Framework lock-inNone — works anywhereNoneStrong (Next.js / React Server Components)

The opinion

If you're shipping a Vercel-hosted Next.js app and want the most opinionated DX possible, uploadthing is fine. If you're shipping anything else — Vite, CRA, Remix, React Native bridge, a one-off internal tool — FilePost is roughly half the moving parts and a third of the price.

S3 directly is the right answer at scale (10+ TB/month). For everything below that, you're paying with your time. The S3 + CloudFront stack is roughly six configuration steps that all need to be right before a single byte uploads. FilePost is one POST.

Where this came from

FilePost exists because the same problem kept showing up: "I need to upload a file from React and get a URL." Every React side project, every internal tool, every dashboard widget. Setting up S3 from scratch took an afternoon every time, and the answer never changed.

One weekend later it was a FastAPI server, a Backblaze B2 bucket, and a Cloudflare CDN. The React surface is exactly what you see above — no clever wrapper, no React-specific binding, just the same multipart endpoint everyone else uses.

When NOT to use FilePost from React

  • You need server-side image transforms (resize, crop, watermark, smart-crop). Cloudinary or Uploadcare do that better — bundled into their upload pipeline.
  • You need OCR or AI tagging on every uploaded file. Filestack has that built in.
  • The user is uploading one file once, then leaving. Use transfer.sh or 0x0.st — no signup needed.
  • You're already pushing 10+ TB/month of egress. You've graduated; raw S3 + CloudFront becomes cheaper at that scale.

Going further

This page is the decision. The deep-dive is the blog post — drag-and-drop with react-dropzone, progress indicators, custom hooks, Next.js App Router API routes, TypeScript types, error-handling patterns, and the production checklist.

Questions we actually get

Do I need a server to upload files from React?

No. The browser can POST directly to https://filepost.dev/v1/upload using fetch and FormData. You only need a server if you want to validate or transform files before they reach FilePost — for example, scanning, watermarking, or stripping EXIF.

Will my API key be exposed in the browser?

If you put the key directly in client code, yes. For production apps, proxy the upload through your own backend (a small Express endpoint, a Next.js API route, a Cloudflare Worker, a Vercel function — anything) so the key stays server-side. For prototypes and internal tools, browser-side keys are fine; rotate from the dashboard if one leaks.

Does FilePost work with react-dropzone?

Yes. react-dropzone gives you the file objects; FilePost takes them. Inside onDrop, pass each file to the same fetch + FormData pattern. There's no FilePost-specific binding to install because the API is plain multipart.

How big can the file be?

50 MB on the free plan, 200 MB on Starter ($9 / mo), 500 MB on Pro ($29 / mo). The upload endpoint accepts standard multipart form data — no special chunked-upload protocol to learn for larger files.

Will the URL expire?

No. Every URL FilePost issues is permanent — it works until you explicitly delete the file via the API or dashboard. Unlike signed S3 URLs (24 h default) or services like file.io and transfer.sh (14 days, or 1 download), there is no expiry.

How is this different from S3 + presigned URLs?

S3 + presigned URLs requires AWS credentials, an IAM policy, a CORS config on the bucket, a signing endpoint on your backend, and a CloudFront distribution if you want a real CDN. FilePost is one POST request from the React component. Time-to-first-upload is roughly 20 minutes for FilePost vs several hours for S3 even when you've done it before.

Ship the upload feature today, not next sprint.

Free tier covers most React side projects forever. Get an API key, paste the snippet, ship it.

Get free API key 300 uploads / mo · 50 MB max · no credit card