Link Search Menu Expand Document

Upload images to Amazon S3

Send every rendered image or PDF to an Amazon S3 bucket you control.


HTML/CSS to Image connects to Amazon S3 by assuming an IAM role in your AWS account. HCTI receives temporary credentials when it needs to write an object, so you do not need to create or share a long-lived AWS access key.

Plan availability

Storage destinations are available on the 10,000 images/month plan or higher. If you’d like to try this on a different plan, email support@htmlcsstoimage.com.

Before you begin

You need:

  • An existing S3 bucket and its AWS region.
  • Permission to create an IAM role and attach a permissions policy.
  • An optional key prefix, such as hcti-renders, if HCTI objects should stay within one part of the bucket.

Open the Storage Destinations dashboard, click Add storage destination, and choose Amazon S3. Enter the bucket, region, and optional key prefix first; HCTI uses those values to generate scoped example policies.

Create the IAM role

The dashboard generates a trust policy and a role permissions policy. They answer different questions and belong in different parts of the IAM role.

Add the trust policy

The trust policy controls who can assume the role. It contains:

  • The HTML/CSS to Image storage writer role as the principal.
  • sts:AssumeRole as the allowed action.
  • An sts:ExternalId condition unique to your HCTI organization.

In AWS IAM, go to Roles, choose Create role, select Custom trust policy, and paste the dashboard-generated trust policy. The external ID prevents the HCTI writer role from using this role for a different organization. Use the generated value without modifying or reusing it.

The trust policy only allows HCTI to assume the role. It does not grant access to your S3 bucket.

Attach the permissions policy

Attach the dashboard-generated role permissions policy as an inline or managed policy. It scopes access to the bucket and optional prefix entered in HCTI.

Permission Required? Purpose
s3:PutObject Required Writes rendered images and the connection-test object.
s3:GetObject Optional Reloads an original for a later resize, crop, or format conversion when Disable HCTI Storage is selected.
s3:DeleteObject Optional Removes the small object created by Test connection. It is not used to delete rendered images.

The generated resources cover rendered objects under arn:aws:s3:::<bucket>/<key-prefix>/*, including connection-test objects under <key-prefix>/.hcti/connection-tests/.

Write access is enough to connect and upload base renders. Include read access if HCTI may need to create a transformation after the initial render while HCTI Storage is disabled. Include delete access if you want connection tests to clean up after themselves.

Finish the destination in HCTI

  1. Finish creating the role and copy its ARN.
  2. Return to the storage destination form and paste the ARN into IAM role ARN.
  3. Confirm the bucket, AWS region, and optional key prefix.
  4. Click Test connection.
  5. Enable and save the destination after the test succeeds.
  6. Copy the destination id.

The connection test assumes the role and writes a small text object. Cleanup is best-effort, so a missing s3:DeleteObject permission does not make a successful write test fail.

Upload an HCTI image to S3

Pass the destination ID as storage_destination_id when you create an image:

curl -X POST https://hcti.io/v1/image \
  -u 'user-id:api-key' \
  -H 'Content-Type: application/json' \
  -d '{
        "url": "https://example.com",
        "storage_destination_id": "your-storage-destination-id"
      }'

Rendering is lazy. With normal HCTI storage enabled, request the image URL returned by the API to render the image and write both the HCTI copy and the S3 copy. With Disable HCTI Storage selected, send an authenticated PUT request to the /v1/store/... URL returned by the create request.

The base object is stored as <key-prefix>/<image-id>.png, or .pdf when the request uses pdf_options. Resized, cropped, and reformatted versions use separate object keys.

Troubleshooting Amazon S3 uploads

  • HCTI cannot assume the role — Confirm that the trust relationship contains the generated HCTI principal and the exact organization-specific external ID.
  • The connection test returns Access Denied — Confirm that the role permissions policy allows s3:PutObject on the bucket and configured prefix, and that a bucket policy does not explicitly deny the request.
  • The connection test uses the wrong endpoint — Confirm that the AWS region in HCTI matches the bucket’s region.
  • A later transformation fails with HCTI Storage disabled — Add s3:GetObject for the configured object prefix.
  • Connection-test objects remain — Add s3:DeleteObject for the .hcti/connection-tests/ path.

AWS documents creating a role with a custom trust policy and using external IDs for third-party access.

Next: use your storage destination

Continue to the Storage Destinations guide for templates, batches, object storage behavior, and the complete PUT /v1/store response.


Need help?

Talk to a human. Please email us support@htmlcsstoimage.com with any questions and we’ll gladly help you get started.


Back to top

Built with extensive integration tests and serious care for developer happiness.
© 2018-2026 Code Happy, LLC.

Page last modified: Aug 27 2026 at 04:31 PM.

Edit this page on GitHub.