Blog

file.io Alternative for curl Uploads (Without the One-Download Limit)

By Pavan Singh6 min read

Founder of sto.care. Writes about file transfer, curl, and the tools developers reach for when scp is not an option.

Swap the hostname: curl -T yourfile https://ul.sto.care. You get a JSON link that allows 10 downloads over 72 hours, so a Slack preview fetching it first does not destroy the file.

Upload
$ curl -T yourfile.zip https://ul.sto.care
{"url":"https://dl.sto.care/mjrxiq1odb","expiresAt":"2026-10-04T20:19:21.615Z"}

No account, no API key, no token. 100 MB per file, 10 uploads per IP per UTC day, links live 72 hours. The syntax barely differs from curl -F "file=@x" https://file.io. What differs is the second fetch: file.io gives you one download, this gives you ten.

First, the thing you should know before migrating

I ran the documented file.io one-liner on 1 October 2026 before writing this. It does not upload. The apex host answers every request with a 301 to www.file.io, and that host is a static site that rejects POST with a 405. Exact output, with only the Cloudflare request IDs trimmed:

Live check, 1 Oct 2026
$ date -u
Thu Oct  1 21:07:03 UTC 2026

$ curl -s -o /dev/null -D - --max-time 20 -F "[email protected]" https://file.io
HTTP/2 301
date: Thu, 01 Oct 2026 21:07:03 GMT
content-type: text/html; charset=UTF-8
location: https://www.file.io/
server: cloudflare

$ curl -sL --post301 --max-time 20 -F "[email protected]" https://file.io
<html>
<head><title>405 Method Not Allowed</title></head>
<body>
<h1>405 Method Not Allowed</h1>
<ul>
<li>Code: MethodNotAllowed</li>
<li>Message: The specified method is not allowed against this resource.</li>
<li>Method: POST</li>
<li>ResourceType: OBJECT</li>
</ul>
</body>
</html>

# A previously published key, from the docs page
$ curl -s -o /dev/null -w "%{http_code}\n" https://www.file.io/download/2ojE41
410

I repeated the POST three times, over HTTP/2 and HTTP/1.1, with and without a browser user agent, with and without ?expires=. Same 301 every time, and api.file.io does not resolve. The marketing site itself is up and returns 200. It still advertises 4 GB uploads and a 14 day default expiry, and its homepage still prints this as a working example:

Documented, not working today
# What file.io's own homepage still shows
$ curl -F "[email protected]" https://file.io
{"success":true,"key":"2ojE41","link":"https://file.io/2ojE41","expiry":"14 days"}

So if you landed here because a script started failing, that 301 is your answer. The site itself is fine: browser uploads still work, but they now post to LimeWire's API, not this endpoint. file.io is a LimeWire property, so its curl API looks abandoned, not briefly broken.

How file.io's model works

file.io is deliberately a one-shot drop box. Upload, share the link, and the file is deleted the moment it is downloaded. Its own homepage quotes a user calling it "like snapchat, but for files", which is a fair summary. Alongside that:

  • 4 GB per transfer, stated twice on the site, on the hero and in the FAQ. Older write-ups say 2 GB; the current number is 4 GB.
  • 14 day default expiry, settable with ?expires=1w, where a bare integer means days and w, M and y mean weeks, months and years.
  • No account required for the free tier, with paid plans on top.
  • maxDownloads and autoDelete exist in the OpenAPI spec on its developers page, so the one-download default is a default rather than a hard law. The free homepage flow does not surface them.

For a one-time secret, that is a genuinely good design. The file not existing any more is the whole security story, and there is nothing left to leak.

When one download is not enough

The failure mode is always the same: something other than your recipient spends the single fetch. Four ways that happens in practice.

Link unfurlers

Paste a URL into Slack, Teams, Discord, iMessage or most email clients, and the platform fetches it server side to build a preview card. That fetch is a download. By the time your colleague clicks, the file is gone and they see a 404. You did everything right and the chat app ate it.

Security scanners

Corporate mail gateways and endpoint protection follow links in incoming messages and pull the payload to scan it. Same outcome, with the added confusion that the scanner is invisible to both ends. This is the single most common reason a file.io link appears to expire instantly inside a company network.

Retries

A download that dies at 90 percent on hotel wifi has still consumed the fetch. There is no resume and no second attempt. Any transfer big enough to be worth sending is big enough to fail halfway.

Two recipients

Send the same link to two people and exactly one of them gets the file, whichever clicks first. For a build artifact going to a team channel, that is not a workable model.

Migrating a script

The multipart form that file.io expects also works against ul.sto.care, because the edge worker unwraps the form envelope and takes the file out of it. In most scripts that makes the migration a hostname change and nothing else:

Migration
# Before: file.io multipart form
curl -F "[email protected]" https://file.io

# Pure hostname swap, the worker unwraps the form envelope
curl -F "[email protected]" https://ul.sto.care

# Or switch to a raw PUT, which is one less layer on the wire
curl -T report.pdf https://ul.sto.care

The only other thing to touch is the field you read out of the JSON. Both services return a flat object, with different key names:

Response shape
# file.io
{"success":true,"key":"2ojE41","link":"https://file.io/2ojE41","expiry":"14 days"}

# ul.sto.care
{"url":"https://dl.sto.care/mjrxiq1odb","expiresAt":"2026-10-04T20:19:21.615Z"}

# jq, before and after
jq -r .link    # file.io
jq -r .url     # ul.sto.care

expiresAt is an ISO 8601 timestamp rather than file.io's human string "14 days", so you can compare it to a clock without parsing English. Errors come back as {"message": "..."} with a meaningful status code. Full details are in the API documentation, and the curl upload guide covers piping, CI steps and downloading with -LO.

A shell function, if you had one wired to file.io:

Shell function
share() { curl -sT "$1" https://ul.sto.care | jq -r .url; }

$ share build.zip
https://dl.sto.care/mjrxiq1odb

The honest limits on this side

Ten downloads is a cap, not unlimited. sto.care is not solving the problem by removing the counter, it is solving it by setting the counter high enough that an unfurler plus a retry plus a few humans all fit. Post the link somewhere public and you will burn through ten fetches, and then it behaves exactly like an expired file.io link. The other constraints are real too: 100 MB per file against file.io's advertised 4 GB, 72 hours against 14 days, and 10 uploads per IP per UTC day.

For bigger files the sto.care web app takes up to 25 GB and holds links for 7 days, still free and still without an account. If you came from a shut-down service rather than from file.io, the transfer.sh alternative post covers that migration, and the 0x0.st alternative post covers the community-run option with a larger size cap.

When file.io is the better choice

Two cases, plainly:

  • You actually want burn after reading. A password, an API key, a recovery code handed to one person over a channel that does not unfurl links. Ten downloads is a worse answer than one here. The temporary.pw password generator that file.io cites as a use case is exactly the right shape for it.
  • The file is over 100 MB and you need the terminal. 4 GB in one curl -F is more than the sto.care curl endpoint will take.

Both of those assume the API starts accepting uploads again. As of the check above it does not, so verify before you depend on it.

FAQ

What is a good file.io alternative for curl uploads?

curl -T yourfile https://ul.sto.care. JSON back with a download URL and an expiry timestamp, no account, 100 MB per file, 10 downloads per file, 72 hour links. The curl -F form works against the same URL, so an old file.io script usually needs only the hostname changed.

Does the file.io API still work?

Checked 1 October 2026: no. https://file.io returns 301 to www.file.io, which answers POST with 405 MethodNotAllowed. Download paths return 410. The marketing site loads fine and still documents the one-liner, which makes the failure confusing to diagnose.

Why did my file.io link expire immediately?

Because something fetched it before your recipient did. file.io deletes the file on first download, and a Slack or Teams preview card, a mail gateway scanner or a failed download attempt all count as that first download.

How many times can a sto.care file be downloaded?

Ten, within 72 hours. Enough to absorb a link preview, a retry and a few recipients. Not enough for a public post, and worth saying out loud: this is a limit, not an absence of one.

What is file.io's actual size limit?

4 GB. Its homepage hero and its FAQ both say 4 GB as of 1 October 2026. The 2 GB figure that circulates in older comparisons is out of date.

Try it

One command, and a link that survives being pasted into a chat app:

Try it
$ curl -T yourfile.zip https://ul.sto.care
{"url":"https://dl.sto.care/mjrxiq1odb","expiresAt":"2026-10-04T20:19:21.615Z"}

Status codes, limits and error shapes are all in the sto.care upload API docs.