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.
| Feature | PutPut | UploadThing |
|---|---|---|
| Signup required | No | Yes (account + API key) |
| Setup time | < 1 minute | 5-10 minutes |
| Framework lock-in | None (plain HTTP) | Next.js / Solid / Svelte |
| Server component needed | No | Yes (file router) |
| Egress fees | $0 | Included (limits apply) |
| Free tier storage | 10 GB | 2 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
// 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());// 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:
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());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"]# 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'"}'// 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-specificUploadThing 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.
No signup required. No credit card.