# How to Configure S3 Bucket CORS to Allow Cross-Origin Requests from a Specific Domain

> Learn how to configure S3 bucket CORS for specific domains using the AWS SDK for JavaScript v3. Easily allow cross-origin requests from your domain with PutBucketCorsCommand.

- Repository: [Amazon Web Services/aws-sdk-js-v3](https://github.com/aws/aws-sdk-js-v3)
- Tags: how-to-guide
- Published: 2026-02-16

---

**To configure S3 bucket CORS for a specific domain, use the `PutBucketCorsCommand` in the AWS SDK for JavaScript v3 to upload a `CORSConfiguration` containing a rule with `AllowedOrigins` set to your domain.**

When building web applications that interact directly with Amazon S3 from the browser, you must configure Cross-Origin Resource Sharing (CORS) policies on your buckets. The AWS SDK for JavaScript v3 provides precise control over these policies through the `PutBucketCorsCommand` and related types defined in the S3 client.

## Understanding S3 CORS Rule Evaluation

S3 stores CORS configurations as XML documents on the bucket's `?cors` sub-resource. When a browser sends a cross-origin request, S3 evaluates the rules in the order they are defined and applies the **first** rule that matches the request's `Origin` header, HTTP method, and request headers.

According to the source code in [`clients/client-s3/src/commands/PutBucketCorsCommand.ts`](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/src/commands/PutBucketCorsCommand.ts) (lines 34-45), this first-match behavior means you should place the most restrictive, domain-specific rules before broader wildcard rules to ensure only intended origins receive access.

## Configure S3 Bucket CORS Using PutBucketCorsCommand

The SDK exposes two primary patterns for applying CORS configurations: the low-level command interface and the higher-level helper method.

### Low-Level Command Approach

Use `PutBucketCorsCommand` when you need explicit control over the command lifecycle or when working with the modular client architecture.

```javascript
import { S3Client, PutBucketCorsCommand } from "@aws-sdk/client-s3";

const client = new S3Client({ region: "us-east-1" });

const corsConfiguration = {
  CORSRules: [
    {
      // Restrict to specific domain only
      AllowedOrigins: ["https://app.example.com"],
      // HTTP methods permitted from this origin
      AllowedMethods: ["GET", "PUT", "POST"],
      // Headers allowed in the request
      AllowedHeaders: ["*"],
      // Response headers exposed to the browser
      ExposeHeaders: ["x-amz-request-id", "x-amz-server-side-encryption"],
      // Cache preflight response for 1 hour
      MaxAgeSeconds: 3600,
    },
  ],
};

await client.send(
  new PutBucketCorsCommand({
    Bucket: "my-public-bucket",
    CORSConfiguration: corsConfiguration,
  })
);

```

The TypeScript interfaces for `CORSConfiguration` and `CORSRule` are defined in [`clients/client-s3/src/models/models_0.ts`](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/src/models/models_0.ts), ensuring type safety when constructing these objects.

### High-Level Helper Method

For simpler scripts, the S3 client instance provides a `putBucketCors` method that wraps the command.

```javascript
import { S3Client } from "@aws-sdk/client-s3";

const s3 = new S3Client({ region: "us-east-1" });

await s3.putBucketCors({
  Bucket: "my-public-bucket",
  CORSConfiguration: {
    CORSRules: [
      {
        AllowedOrigins: ["https://app.example.com"],
        AllowedMethods: ["GET"],
        AllowedHeaders: ["*"],
        ExposeHeaders: ["x-amz-server-side-encryption"],
        MaxAgeSeconds: 3000,
      },
    ],
  },
});

```

The end-to-end test suite in [`clients/client-s3/test/e2e/s3-bucket-features.e2e.spec.ts`](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/test/e2e/s3-bucket-features.e2e.spec.ts) (lines 34-45) demonstrates this exact pattern, validating that the configuration persists correctly on the bucket.

## Verifying Your S3 CORS Configuration

After applying the configuration, retrieve it using `GetBucketCorsCommand` or `s3.getBucketCors` to confirm the rules are active.

```javascript
const result = await s3.getBucketCors({ Bucket: "my-public-bucket" });
console.log(JSON.stringify(result.CORSRules, null, 2));

```

The response should contain the `AllowedOrigins` array with your specific domain, confirming that S3 will reject cross-origin requests from unauthorized origins while allowing your designated domain.

## Summary

- **Use `PutBucketCorsCommand`** (or `s3.putBucketCors`) to upload CORS rules to an S3 bucket via the AWS SDK for JavaScript v3.
- **Specify the exact domain** in the `AllowedOrigins` array of your `CORSRule` to restrict access to a single origin.
- **Order matters**: S3 applies the first matching rule, so place specific domain rules before wildcard rules.
- **Verify** the configuration with `GetBucketCorsCommand` to ensure the policy is active.

## Frequently Asked Questions

### What is the correct format for AllowedOrigins when configuring S3 CORS?

The `AllowedOrigins` field must contain the complete origin string including the protocol, domain, and port (if non-standard). For example, use `https://app.example.com` rather than just `app.example.com`. According to the SDK source in [`clients/client-s3/src/models/models_0.ts`](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/src/models/models_0.ts), this is an array of strings where each entry represents one permitted origin.

### How does S3 handle multiple CORS rules in the same configuration?

S3 evaluates CORS rules in the order they are defined in the `CORSRules` array and applies the **first** rule that matches the request's origin, method, and headers. As documented in [`clients/client-s3/src/commands/PutBucketCorsCommand.ts`](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/src/commands/PutBucketCorsCommand.ts), this first-match behavior means you should structure your rules from most specific to most general to prevent unintended access.

### Why is my S3 CORS configuration not working for my specific domain?

Common issues include: omitting the protocol (http vs https) in `AllowedOrigins`, not including the specific HTTP method in `AllowedMethods`, or having a more permissive rule earlier in the `CORSRules` array that matches first. Verify your configuration using `GetBucketCorsCommand` and check the browser's developer console for the exact preflight error to identify which CORS header is missing.

### Can I use wildcards in AllowedOrigins when configuring S3 CORS?

While S3 supports the wildcard `*` in `AllowedOrigins` to allow any domain, you cannot use partial wildcards like `https://*.example.com`. For specific subdomain patterns, you must list each subdomain explicitly or use a single wildcard for all origins. The SDK's `CORSRule` interface in [`clients/client-s3/src/models/models_0.ts`](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-s3/src/models/models_0.ts) treats `AllowedOrigins` as a string array where `*` is a valid entry but regex patterns are not supported.