Is it possible to upload to S3 directly from URL using POST?
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
No, Amazon S3 cannot take a public URL in a POST request and fetch that remote file on your behalf. S3 accepts bytes you upload, but it does not implement a “pull from arbitrary URL” feature in its normal upload API.
What S3 POST Actually Does
An S3 POST upload is an HTTP form upload. The client sends the file body and form fields to S3, and S3 stores exactly those bytes in the bucket.
That means the POST request must already contain the content to upload. A URL string by itself is only metadata. S3 will store the string if you send it, but it will not dereference the URL, download the file, and then save the fetched content.
This distinction is the core answer.
Direct Browser Upload Versus Remote Fetch
Developers often mix up two different ideas:
- browser or mobile app uploads bytes directly to S3 with a pre-signed POST or PUT
- S3 fetches a remote file from another server
The first is supported and common. The second is not a built-in S3 feature for arbitrary internet URLs.
Here is a typical pre-signed POST flow on the server side using Python and boto3.
That lets a client upload file bytes directly to S3, but the client still has to provide the bytes.
If the Source Is a URL, You Need an Intermediary
If your input is a remote URL, some application component has to fetch the file first and then upload the resulting bytes to S3. That intermediary can be:
- your backend server
- an AWS Lambda function
- a container job
- any service with network access to the remote URL and write access to S3
A small Python example makes the pattern concrete.
This is the normal solution when the file lives on the public internet.
Server-Side Copy Is Different
S3 does support server-side copying between S3 objects. If the source is already in S3 and you have permission, CopyObject can copy data without downloading it to your application first.
That is efficient, but it applies to S3-to-S3 copies, not arbitrary URLs on the public web.
Why This Limitation Exists
If S3 accepted arbitrary remote URLs directly, it would need to act as an outbound HTTP client, handle remote authentication schemes, follow redirects, manage timeouts, and absorb the security implications of fetching untrusted content from anywhere.
S3 is designed as object storage, not as a general URL ingestion service.
That is why the clean architecture is to keep the fetch logic in your application layer, where you can validate the URL, restrict allowed hosts, enforce size limits, scan content, and decide what metadata to store.
Operational Considerations
When building a URL-to-S3 import feature, plan for:
- timeouts on slow remote servers
- file size limits
- content-type validation
- duplicate detection or key naming strategy
- antivirus or malware scanning if content is untrusted
Those checks belong in the intermediary anyway, which is another reason a direct S3 URL fetch would not solve the real problem by itself.
Common Pitfalls
A common mistake is sending the remote URL as the POST body and expecting S3 to interpret it as an instruction. S3 will not fetch it.
Another mistake is using pre-signed POST and assuming it changes the semantics of upload. It only delegates permission for direct client upload of bytes.
Developers also overlook the difference between arbitrary URL imports and S3-to-S3 copy operations. Only the latter is a built-in server-side storage operation.
Finally, avoid streaming untrusted remote content straight into your bucket without validation. The intermediary should enforce at least basic safety checks.
Summary
- S3 POST uploads bytes; it does not fetch a remote file from a URL for you.
- To import from a URL, use a backend, Lambda, or another intermediary to download and re-upload the content.
- Pre-signed POST helps clients upload directly, but the client still supplies the bytes.
- S3 server-side copy works only for S3 objects, not arbitrary public URLs.
- A custom import layer is the right place for validation, timeouts, and security controls.
Related reading
- Is it possible to use AWS as a web host?
- Is it possible to use Istio without kubernetes or docker?
- Is it possible to use Socket.io with AWS Lambda?
- Is it possible to use Socket.io with AWS Lambda?
- Is Kubernetes emptyDir different from no volume at all
- Is MassTransit with Azure Service Bus a good fit for tenant-isolated on-prem agents?
- Is multi-AZ RDS really worth it?
- Is the Amazon .NET AWS SDK's AmazonS3 thread safe?

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.