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
Finish creating the role and copy its ARN.
Return to the storage destination form and paste the ARN into IAM role ARN.
Confirm the bucket, AWS region, and optional key prefix.
Click Test connection.
Enable and save the destination after the test succeeds.
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:
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.