Skip to content

PutPut vs the Alternatives

Developers waste hours evaluating file upload services. We did the work for you. Each comparison breaks down pricing, setup time, lock-in, and what actually matters when you just need to upload a file and get a URL.

PutPut vs UploadThing

UploadThing is a great file upload library for Next.js, but it requires a framework-specific file router and an account. PutPut is framework-agnostic and works with plain HTTP requests.

FeaturePutPutUploadThing
Signup required No Yes (account + API key)
Setup time< 1 minute5-10 minutes
Framework lock-in None (plain HTTP) Next.js / Solid / Svelte
Server component needed No Yes (file router)
Egress fees $0Included (limits apply)
Free tier storage10 GB2 GB
AI-friendly docs docs.putput.io No
Self-hostable Yes (Cloudflare) No
Direct-to-storage uploads Yes (R2 presigned) Yes
Guest tokens (no auth) Yes No

Code comparison

PutPut
// Works in any framework or plain JS
const tok = await fetch('/api/v1/auth/guest',
  { method: 'POST' }).then(r => r.json());

const pre = await fetch('/api/v1/upload/presign',
  { method: 'POST',
    headers: { Authorization: `Bearer ${tok.token}` },
    body: JSON.stringify({ filename: 'doc.pdf',
      content_type: 'application/pdf' }) }
).then(r => r.json());

await fetch(pre.upload_url,
  { method: 'PUT', body: file });

const result = await fetch('/api/v1/upload/confirm',
  { method: 'POST',
    headers: { Authorization: `Bearer ${tok.token}` },
    body: JSON.stringify({ upload_id: pre.upload_id }) }
).then(r => r.json());
UploadThing
// 1. Define file router (server)
import { createUploadthing }
  from 'uploadthing/next';

const f = createUploadthing();
export const uploadRouter = {
  docUploader: f({
    pdf: { maxFileSize: '4MB' }
  })
    .middleware(async () => {
      // Auth check required
      return { userId: 'abc' };
    })
    .onUploadComplete(async ({ file }) => {
      console.log('uploaded', file.url);
    }),
};

// 2. Create API route (server)
import { createRouteHandler }
  from 'uploadthing/next';
export const { GET, POST } =
  createRouteHandler({ router });

// 3. Use component (client)
import { UploadButton }
  from '@uploadthing/react';
<UploadButton endpoint="docUploader" />

They ship a React library. We ship an API.

UploadThing works well if your entire stack is React or Next.js. But what happens when you add a mobile app, a CLI tool, or an AI agent? You need a different integration for each one — or you rewrite.

PutPut is plain HTTP. Any language, any framework, any runtime. Here's the same upload in three languages:

PutPut — JavaScript
const res = await fetch(presignUrl,
  { method: 'PUT', body: file });
const { url } = await fetch(confirmUrl,
  { method: 'POST',
    headers: { Authorization: `Bearer ${token}` },
    body: JSON.stringify({ upload_id }) }
).then(r => r.json());
PutPut — Python
import requests

requests.put(presign_url, data=file_bytes)
result = requests.post(confirm_url,
  headers={"Authorization": f"Bearer {token}"},
  json={"upload_id": upload_id})
url = result.json()["url"]
PutPut — cURL
# Upload the file
curl -X PUT "$PRESIGN_URL" \
  --data-binary @photo.jpg

# Confirm and get the public URL
curl -X POST "$API/upload/confirm" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"upload_id": "'$UPLOAD_ID'"}'
UploadThing
// Requires Next.js or Solid or Svelte
import { createUploadthing }
  from 'uploadthing/next';
import { UploadButton }
  from '@uploadthing/react';

// Needs: file router, API route handler,
// React component, and server middleware
// — all framework-specific

UploadThing requires a framework-specific file router, server middleware, and a React (or Solid/Svelte) component. Switching frameworks means rewriting your upload integration.

Frequently asked questions

What's the difference between PutPut and UploadThing?

PutPut works with any framework via plain HTTP calls. UploadThing requires a specific framework integration (Next.js, Solid, Svelte). PutPut also offers 10 GB free storage vs UploadThing's 2 GB.

Is PutPut free?

Yes. PutPut has a free tier with 10 GB storage, unlimited files, and $0 egress. No credit card required.

Does PutPut require a specific framework?

No. PutPut is framework-agnostic. It works with Next.js, SvelteKit, Nuxt, Rails, or any language that can make HTTP requests.

Does PutPut have egress fees?

No. PutPut has $0 egress fees on every plan, powered by Cloudflare R2.

Get started for free

No signup required. No credit card.

v0.4.77