S3
direct upload
URL
POST request
Amazon Web Services

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.

Practice system design

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.

python
1import boto3
2
3s3 = boto3.client("s3")
4response = s3.generate_presigned_post(
5    Bucket="my-upload-bucket",
6    Key="uploads/example.jpg",
7    ExpiresIn=300,
8)
9
10print(response["url"])
11print(response["fields"])

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.

python
1import requests
2import boto3
3
4
5def upload_from_url(url, bucket, key):
6    response = requests.get(url, timeout=30)
7    response.raise_for_status()
8
9    s3 = boto3.client("s3")
10    s3.put_object(
11        Bucket=bucket,
12        Key=key,
13        Body=response.content,
14        ContentType=response.headers.get("Content-Type", "application/octet-stream"),
15    )
16
17
18upload_from_url(
19    "https://example.com/image.jpg",
20    "my-upload-bucket",
21    "imports/image.jpg",
22)

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.

python
1import boto3
2
3s3 = boto3.client("s3")
4s3.copy_object(
5    Bucket="destination-bucket",
6    Key="copied/file.txt",
7    CopySource="source-bucket/original/file.txt",
8)

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
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track 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.

Practice system design

All Rights Reserved.