How to Upload a File With curl (One Command, No API Key)
You want to get a file off a server and into someone else's hands without leaving the terminal. Here is the shortest path:
$ curl -T yourfile.mp4 https://ul.sto.care
{"url":"https://dl.sto.care/xk92mq7p","expiresAt":"2026-07-24T09:14:07.000Z"}That is the whole thing. curl -T issues a PUT with your file as the body, and the response is JSON with a shareable download URL and an ISO 8601 expiry timestamp. No auth, no signup, no API key. Send the url to whoever needs the file.
The rules
The endpoint is sto.care's open upload API. The constraints are deliberately simple:
- PUT or POST to
https://ul.sto.care. With-T, curl takes the filename from the local file. - Max 100 MB per file. Bigger files belong in the web app (up to 5 GB).
- Content-Length is required.
curl -Tsets it for you. Chunked transfer encoding gets rejected with a 411. - 10 uploads per IP per UTC day. After that you get a 429 until UTC midnight.
- Files expire after 72 hours. The link stops working after that.
- Errors are JSON in the shape
{"message": "..."}, with a meaningful status code.
Downloading is just as short. curl -LO saves the file under its original name, which is preserved via the Content-Disposition header:
$ curl -LO https://dl.sto.care/xk92mq7p
$ ls
yourfile.mp4Forgot the rules mid-session? curl https://ul.sto.care (a plain GET) prints plain-text usage help. There is also a machine-readable reference at sto.care/llms.txt for AI agents, and the full API docs cover every status code.
Other ways to upload files with curl
A hosted drop box is not always what you want. Here are the other patterns, and when each makes sense.
curl -T to your own server
If you control the destination machine, curl -T can PUT straight to any HTTP server that accepts uploads, and scp or rsync do the same job over SSH. The tradeoff: you need a server, credentials, and something on the other end that stores the file. Good for recurring transfers to infrastructure you own; overkill for "here, have this file."
# PUT to your own HTTP server
$ curl -T backup.tar.gz https://files.example.com/uploads/ --user me:secret
# The same job over SSH
$ scp backup.tar.gz [email protected]:/var/uploads/curl -F for multipart forms
curl -F sends multipart/form-data, the same format a browser file input uses. You need it when the receiving endpoint expects a form field, not a raw body:
$ curl -F "[email protected]" https://example.com/upload
# 0x0.st uses this form style
$ curl -F "[email protected]" https://0x0.st0x0.st is worth knowing about: community-run, up to 512 MB, no account. It is a hobby project sustained by donations, so treat it accordingly, but it has been around for years and it is genuinely useful for files too big for the 100 MB cap.
What happened to transfer.sh?
For years the answer to this whole article was transfer.sh. It shut down, and its domain no longer serves the service, but the workflow it popularized (curl -T file https://..., get a link back) is exactly what ul.sto.care implements. If you had transfer.sh in a script, swapping the URL is usually the entire migration.
| Method | Max size | Auth | Expiry |
|---|---|---|---|
| curl -T ul.sto.care | 100 MB | None | 72 hours |
| curl -F 0x0.st | 512 MB | None | 30–365 days |
| Your own server | Your call | SSH / creds | Your call |
| transfer.sh | Shut down | ||
Scripting recipes
A one-liner for your .bashrc or .zshrc, using jq to pull the URL out of the JSON:
share() { curl -sT "$1" https://ul.sto.care | jq -r .url; }
$ share demo.mp4
https://dl.sto.care/xk92mq7pIn CI, the same trick shares a build artifact with anyone on the team without wiring up storage buckets or tokens:
- name: Share build artifact
run: |
curl -sT dist/app.zip https://ul.sto.care > result.json
echo "Download: $(jq -r .url result.json)"One gotcha with pipes: uploading from stdin does not work, because curl cannot know the Content-Length of a stream and falls back to chunked encoding, which the API rejects with a 411. Land the data in a temp file first:
# This fails with 411: stdin has no Content-Length
$ pg_dump mydb | curl -T - https://ul.sto.care
# Write to a temp file first, then upload
$ pg_dump mydb > /tmp/dump.sql
$ curl -T /tmp/dump.sql https://ul.sto.careFor files over 100 MB
The curl endpoint is tuned for quick terminal shares, not for moving a 4 GB video export. For that, the sto.care web app takes files up to 5 GB and keeps the link alive for 7 days instead of 72 hours. Still free, still no account; a one-time email verification is the only step. Our large file sending guide covers the alternatives if you need even more.
FAQ
How do I upload a file with curl?
curl -T yourfile.mp4 https://ul.sto.care. The -T flag PUTs the file as the request body and sets Content-Length for you. The JSON response contains the shareable download URL and an expiry timestamp.
Is there a free file upload API without an API key?
Yes. ul.sto.care accepts PUT or POST with no authentication: 100 MB per file, 10 uploads per IP per UTC day, links live 72 hours. 0x0.st is a community-run alternative with a 512 MB cap.
What replaced transfer.sh?
transfer.sh shut down, but its curl -T workflow lives on. ul.sto.care works the same way and returns JSON instead of a bare URL, so it is script-friendly out of the box. Swapping the domain in an old transfer.sh script is usually all it takes.
How do I download the file back with curl?
curl -LO https://dl.sto.care/<id>. The -O flag writes the file to disk under its original filename, which the server preserves via Content-Disposition.
Why does my curl upload fail with 411 Length Required?
You streamed from stdin (curl -T -), so curl used chunked encoding and never sent a Content-Length header, which the API requires. Write the stream to a temporary file and upload that instead.