Skip to main content
RapidDev - Software Development Agency
retool-integrationsRetool Native Resource

How to Integrate Retool with AWS S3

Connect Retool to AWS S3 using Retool's native S3 connector. Navigate to Resources tab, add an AWS S3 resource, provide your IAM credentials or access key, and immediately list buckets, browse objects, upload files with the dedicated S3 Uploader component, and generate presigned URLs for secure downloads. All requests proxy through Retool's backend, keeping AWS credentials off the client.

What you'll learn

  • How to create an AWS S3 resource in Retool using IAM access keys or role-based authentication
  • How to list buckets and browse S3 objects using the Retool query editor
  • How to use Retool's dedicated S3 Uploader component for file uploads
  • How to generate presigned URLs for secure, time-limited file downloads
  • How to build a complete file management dashboard with upload, browse, and download capabilities
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate16 min read15 minutesStorageLast updated April 2026RapidDev Engineering Team
TL;DR

Connect Retool to AWS S3 using Retool's native S3 connector. Navigate to Resources tab, add an AWS S3 resource, provide your IAM credentials or access key, and immediately list buckets, browse objects, upload files with the dedicated S3 Uploader component, and generate presigned URLs for secure downloads. All requests proxy through Retool's backend, keeping AWS credentials off the client.

Quick facts about this guide
FactValue
ToolAWS S3
CategoryStorage
MethodRetool Native Resource
DifficultyIntermediate
Time required15 minutes
Last updatedApril 2026

Why Connect Retool to AWS S3?

AWS S3 is where engineering teams store everything that doesn't belong in a database: uploaded documents, generated reports, exported CSVs, application logs, media assets, and backup archives. Connecting Retool to S3 lets your operations team, support staff, and internal users browse, upload, and manage these files through a purpose-built interface rather than navigating the AWS console, which requires IAM access and AWS familiarity.

Retool's native S3 connector includes a purpose-built S3 Uploader component — a drag-and-drop file upload widget that handles multipart uploads, file type restrictions, and size limits without any backend code. This is the key differentiator from connecting S3 via REST API: the S3 Uploader works out of the box once your resource is configured. Combine it with the S3 List Objects query to build a full file browser, presigned URL generation for secure downloads, and metadata display for a complete internal file management portal.

Common use cases include document management portals where users upload contracts and the app stores them in a structured S3 path, log analysis tools that list S3 objects by prefix and display file sizes and modification dates, report delivery dashboards that generate presigned download URLs for scheduled CSV exports, and asset management panels for marketing teams to organize and retrieve media files stored in S3.

Integration method

Retool Native Resource

Retool includes a dedicated AWS S3 connector that authenticates via AWS access keys or IAM role assumption and exposes list, get, put, and delete object operations directly in the query editor. The connector also powers Retool's dedicated S3 Uploader component, which provides a drag-and-drop file upload UI that writes directly to your S3 bucket without any additional backend code. All requests proxy server-side through Retool, so AWS credentials never reach the browser.

Prerequisites

  • An AWS account with at least one S3 bucket
  • An IAM user or role with the necessary S3 permissions (s3:ListBucket, s3:GetObject, s3:PutObject, s3:DeleteObject)
  • AWS Access Key ID and Secret Access Key for the IAM user (or IAM role ARN for role assumption)
  • A Retool account (Cloud or self-hosted) with permission to create Resources
  • For Retool Cloud: S3 bucket policy or IAM policy that allows access from Retool's IP ranges (or use IAM role assumption)

Step-by-step guide

1

Create an IAM user and configure S3 permissions in AWS

Before configuring Retool, set up proper AWS IAM permissions. In the AWS Console, navigate to IAM → Users → Create User. Create a dedicated user for Retool (e.g., retool-s3-integration) rather than using personal credentials. This makes it easy to rotate credentials and apply minimal permissions. Attach an inline or managed policy to this user. The minimum policy for a read/write Retool integration requires s3:ListAllMyBuckets (to list buckets), s3:ListBucket (to list objects in a specific bucket), s3:GetObject, s3:PutObject, and optionally s3:DeleteObject if you want delete capability. Restrict the policy to specific buckets using the Resource field rather than granting access to all buckets. After creating the user, navigate to the user's Security Credentials tab and create an Access Key. Select 'Application running outside AWS' as the use case. Copy the Access Key ID and Secret Access Key — the secret is only shown once. For production environments with self-hosted Retool running on EC2 or ECS: instead of access keys, use IAM Role assumption. Attach an IAM role to your Retool instance with the appropriate S3 permissions. In the Retool resource configuration, select 'Use Instance Role' instead of providing access keys. This is more secure because credentials rotate automatically and are never stored as configuration values.

retool-s3-iam-policy.json
1{
2 "Version": "2012-10-17",
3 "Statement": [
4 {
5 "Effect": "Allow",
6 "Action": [
7 "s3:ListAllMyBuckets"
8 ],
9 "Resource": "arn:aws:s3:::*"
10 },
11 {
12 "Effect": "Allow",
13 "Action": [
14 "s3:ListBucket",
15 "s3:GetBucketLocation"
16 ],
17 "Resource": "arn:aws:s3:::your-bucket-name"
18 },
19 {
20 "Effect": "Allow",
21 "Action": [
22 "s3:GetObject",
23 "s3:PutObject",
24 "s3:DeleteObject"
25 ],
26 "Resource": "arn:aws:s3:::your-bucket-name/*"
27 }
28 ]
29}

Pro tip: Never reuse your personal AWS credentials or root account keys for Retool. Always create a dedicated IAM user with the minimum required permissions. If your bucket has sensitive data, restrict the IAM policy to specific prefixes (arn:aws:s3:::your-bucket/retool-uploads/*) rather than the entire bucket.

Expected result: An IAM user exists with an Access Key ID and Secret Access Key, and a policy granting the required S3 permissions to the specific bucket you want Retool to access.

2

Add the AWS S3 Resource in Retool

In your Retool instance, navigate to the Resources tab in the left sidebar. Click Add Resource. In the resource type selector, find 'Amazon S3' under the Storage & Files category, or search for 'S3'. In the resource configuration panel, enter a descriptive name such as 'AWS S3 Production' or 'Media Assets Bucket'. In the Authentication section, select 'AWS Access Key' and enter your IAM user's Access Key ID and Secret Access Key. Specify the AWS region where your bucket resides (e.g., us-east-1, eu-west-1). This must match the bucket's region. If you have buckets in multiple regions, create separate Retool S3 resources for each region. Optionally, specify a default bucket name. If you do this, queries using this resource will default to that bucket. Leave it blank if you want to specify the bucket dynamically in each query. Click Save Changes. Retool will test the connection by attempting to list your S3 buckets. If successful, a green 'Connection successful' message appears. For Retool Cloud deployments: your S3 bucket must be accessible from Retool's IP ranges (35.90.103.132/30 and 44.208.168.68/30 for us-west-2). If your bucket has a bucket policy that restricts access by IP, add these ranges. Alternatively, if your bucket is public-read, no IP restrictions apply. For maximum security with Retool Cloud, use IAM Role assumption with a cross-account trust policy pointing to Retool's AWS account.

Pro tip: If you use multiple AWS environments (production, staging), create separate Retool S3 resources for each. Use Retool's resource environments feature (available on Business plan) to automatically use the staging S3 resource in your staging Retool environment and the production S3 resource in production, without changing any query code.

Expected result: The AWS S3 resource appears in your Resources list with a green Connected status. You can see it listed when creating a new query in any Retool app.

3

Query S3 buckets and list objects in the query editor

Open a Retool app and create a new query. Select your AWS S3 resource. The S3 query editor shows an Action dropdown with the available S3 operations: List Buckets, List Objects in Bucket, Get Object, Get Presigned URL, Upload File, Delete File, and Copy File. Create a query named listBuckets with action List Buckets. Run it to verify the connection returns your bucket list. This is a useful diagnostic query — if it works, your IAM credentials are valid. Create a second query named listObjects with action List Objects in Bucket. Set Bucket to your target bucket name (either hardcoded or via a component reference like {{ bucketSelect.value }}). Set the Prefix parameter to filter objects by path prefix — for example, documents/ to list only the documents folder, or {{ prefixInput.value }} to make it dynamic. The S3 List Objects action returns an array of objects with Key (full path), Size (bytes), LastModified (ISO timestamp), and ETag fields. Bind the results to a Table component by setting the Table's data property to {{ listObjects.data }}. Add a JavaScript transformer to the listObjects query to format the file size and date for display. Go to the query's Advanced tab → Add Transformer. The transformer receives the raw S3 response in the data variable.

listObjectsTransformer.js
1// listObjects transformer — format S3 object list for display
2const objects = data || [];
3
4return objects.map(obj => ({
5 filename: obj.Key.split('/').pop() || obj.Key,
6 path: obj.Key,
7 size: obj.Size < 1024
8 ? `${obj.Size} B`
9 : obj.Size < 1048576
10 ? `${(obj.Size / 1024).toFixed(1)} KB`
11 : `${(obj.Size / 1048576).toFixed(2)} MB`,
12 lastModified: new Date(obj.LastModified).toLocaleDateString('en-US', {
13 year: 'numeric', month: 'short', day: 'numeric'
14 }),
15 rawSize: obj.Size,
16 rawKey: obj.Key
17})).sort((a, b) => new Date(b.lastModified) - new Date(a.lastModified));

Pro tip: S3 List Objects returns a maximum of 1,000 objects per request. For buckets with more than 1,000 objects in a prefix, use the NextContinuationToken from the response to implement pagination. Pass the token back as the Continuation Token parameter in subsequent queries.

Expected result: A Table component displays all S3 objects in the specified prefix with formatted filename, size, and last modified date columns. Changing the prefix filter updates the list dynamically.

4

Use the S3 Uploader component for file uploads

Retool includes a dedicated S3 Uploader component that provides drag-and-drop file upload functionality directly to your S3 bucket — no backend code required. This is the primary differentiator of the native S3 connector versus a generic REST API integration. In the Component panel on the right side of the Retool editor, search for 'S3 Uploader' and drag it onto your canvas. With the component selected, configure it in the right-hand properties panel. Set the S3 resource to your configured AWS S3 resource. Set the Bucket to your target bucket (either hardcoded or dynamic: {{ bucketSelect.value }}). Set the Key Prefix to define where uploads are stored — for example, uploads/{{ currentUser.email }}/ to organize files by uploader. If the key prefix contains the full desired filename, the component uses it directly; otherwise it appends the original filename. Configure the component's Allowed File Types to restrict what can be uploaded (e.g., .pdf,.png,.csv). Set Max File Size in MB to prevent oversized uploads. The S3 Uploader has a built-in event handler: On Upload Success. Wire this to trigger your listObjects query to refresh the file table after each upload, and optionally show a success notification using Retool's built-in notification system. For programmatic uploads (uploading files that come from other Retool components, not user drag-and-drop): use the Upload File action type in a standard S3 query. Reference a FilePicker component's value: set the File Body to {{ filePicker1.value[0] }} to upload the selected file. This approach gives you more control over the upload process, including custom metadata and content-type headers.

uploadDocument_config.json
1// Programmatic upload using Upload File action type
2// S3 Query: uploadDocument
3// Action: Upload File
4// Configuration:
5{
6 "bucket": "your-bucket-name",
7 "key": "{{ `documents/${currentUser.email}/${moment().format('YYYY-MM-DD')}/${filePicker1.value[0].name}` }}",
8 "fileBody": "{{ filePicker1.value[0] }}",
9 "contentType": "{{ filePicker1.value[0].type }}",
10 "acl": "private"
11}

Pro tip: The S3 Uploader component uploads files with private ACL by default, meaning uploaded files are not publicly accessible. To share files with internal users, generate a presigned URL (explained in the next step) rather than making objects public. This is the secure pattern for internal tools.

Expected result: The S3 Uploader component displays a drag-and-drop zone. When a file is dropped or selected, it uploads to the configured S3 path. On success, the file list table refreshes to include the newly uploaded file.

5

Generate presigned URLs for secure file downloads

Presigned URLs allow users to download private S3 objects without requiring AWS credentials — the URL itself carries time-limited authorization. This is the correct pattern for internal tools: objects remain private in S3, but authorized users can download them via a secure, temporary URL. Create a query named getPresignedUrl with action 'Get Presigned URL'. Set the Bucket and Key parameters — the Key should reference the selected row in your file table: {{ table1.selectedRow.data.rawKey }}. Set the Expiration Time in seconds (3600 = 1 hour, 86400 = 24 hours). In your file Table component, add an Action Column with a 'Download' button. Set the button's onClick to trigger the getPresignedUrl query. In the query's On Success event handler, add a handler to open the URL in a new tab: use the built-in 'Open URL' action with the URL set to {{ getPresignedUrl.data }}. For a better UX, you can also display the presigned URL in a Text component or copy it to clipboard using Retool's built-in clipboard utilities. For object metadata: Retool's S3 connector doesn't directly expose a Head Object action for fetching metadata without downloading the file. If you need metadata (content type, custom metadata tags), use the Get Object action with a range request, or store metadata in a separate database table when files are uploaded. For managing large numbers of files across multiple buckets: consider building a metadata layer — a PostgreSQL or Retool Database table that records the S3 key, uploader, upload timestamp, and any business-specific tags when files are uploaded. This enables rich querying and filtering that S3's own API doesn't support efficiently.

getPresignedUrl_config.json
1// getPresignedUrl query configuration
2// Action: Get Presigned URL
3// Bucket: your-bucket-name
4// Key: {{ table1.selectedRow.data.rawKey }}
5// Expiration: 3600
6
7// On Success event handler (JavaScript):
8const url = getPresignedUrl.data;
9window.open(url, '_blank');
10
11// Transformer to format the presigned URL response (if needed):
12// return { downloadUrl: data, expiresAt: new Date(Date.now() + 3600000).toISOString() };

Pro tip: Presigned URLs expire after the configured duration, so avoid storing them in your database. Generate a fresh presigned URL on demand each time a user requests a download. For URLs that need to be embedded in emails or reports, generate them with a longer expiry (24-48 hours) at send time.

Expected result: Clicking the Download button in the file table generates a presigned URL and opens the file in a new browser tab. The file downloads without requiring the user to have AWS credentials.

Common use cases

Build an internal document upload and management portal

Create a Retool app with a S3 Uploader component that allows team members to upload files to a specific S3 bucket and path prefix. Display a Table of all uploaded files with filename, file size, upload date, and uploader info (stored in a separate database). Add a Download button that generates a presigned URL for each file, and a Delete button with a confirmation modal.

Retool Prompt

Build a document management portal with an S3 Uploader component for uploading files to the 'documents/contracts/' prefix in our S3 bucket. Show a Table of all files in that path with columns for filename, file size in KB, last modified date, and a Generate Download Link button. The download link should be a presigned URL valid for 1 hour. Add a Delete button with a confirmation dialog.

Copy this prompt to try it in Retool

Create a log file browser for S3-archived application logs

Build a Retool dashboard that lists S3 objects in a logs bucket, filtered by date prefix (logs/2024/03/). Display a Table with file names, sizes, and last modified timestamps. Allow ops engineers to click a log file to generate a presigned URL, and embed a text preview of the log content in a modal by fetching the object via the presigned URL.

Retool Prompt

Build a log browser that lists all objects in the 'application-logs' S3 bucket filtered by a date prefix matching the selected month (logs/YYYY/MM/). Show a Table with object key, size in MB, and last modified. When an engineer selects a row, show a View Log button that generates a presigned URL and opens the log file content in a modal text area.

Copy this prompt to try it in Retool

Build a report delivery dashboard with scheduled exports

Create an admin panel showing all report files in an S3 'reports/' prefix, organized by report type and date. Allow users to browse available reports, see file metadata, and generate time-limited presigned download URLs. Include a search box to filter by filename prefix and a date range picker to filter by upload date.

Retool Prompt

Build a report delivery dashboard showing all files in the 'reports/' S3 prefix grouped by report type subfolder. Show file name, size, creation date, and a Download button per row. The download button should generate a presigned URL valid for 24 hours. Add a text search for filtering by filename and a date range picker to filter files by LastModified date.

Copy this prompt to try it in Retool

Troubleshooting

Connection test fails with 'InvalidAccessKeyId' or 'SignatureDoesNotMatch' error

Cause: The AWS Access Key ID or Secret Access Key entered in the Retool resource configuration is incorrect, has been deactivated, or contains copy-paste errors such as leading/trailing whitespace.

Solution: Verify your access key in the AWS IAM console under the user's Security Credentials tab. Ensure the key is Active (not Inactive or deleted). Re-enter the Secret Access Key carefully — it can only be viewed once at creation time. If you no longer have the Secret Access Key, deactivate the old key and create a new one. Paste credentials directly from your password manager rather than retyping to avoid character errors.

List Objects returns an empty array even though files exist in the bucket

Cause: The IAM user lacks the s3:ListBucket permission on the specific bucket ARN (not the object ARN), or the Prefix filter in the query does not match the actual path structure of your objects. S3 key prefixes are case-sensitive.

Solution: Verify the IAM policy grants s3:ListBucket on arn:aws:s3:::your-bucket-name (the bucket itself, without a trailing slash or wildcard). Check the Prefix parameter in your Retool query — if your objects are stored as logs/2024/03/app.log, the prefix logs/ will list them, but Logs/ (capital L) will return nothing. Use the AWS S3 console to browse the actual key structure and copy the exact prefix.

S3 Uploader shows 'Access Denied' when attempting to upload a file

Cause: The IAM user has s3:ListBucket and s3:GetObject permissions but is missing s3:PutObject. Alternatively, the bucket has a restrictive bucket policy that explicitly denies PutObject, overriding the IAM user's allow policy.

Solution: In AWS IAM, verify the user policy includes s3:PutObject for the bucket's object ARN (arn:aws:s3:::your-bucket/*). Also check the S3 bucket's Bucket Policy in the S3 console — an explicit Deny in a bucket policy overrides IAM user allows. If a bucket policy exists, add a statement allowing s3:PutObject from the Retool IAM user's ARN.

typescript
1{
2 "Effect": "Allow",
3 "Principal": {"AWS": "arn:aws:iam::YOUR_ACCOUNT_ID:user/retool-s3-integration"},
4 "Action": "s3:PutObject",
5 "Resource": "arn:aws:s3:::your-bucket-name/*"
6}

Presigned URLs return 'Request has expired' immediately after generation

Cause: Clock skew between Retool's server and AWS. S3 presigned URLs are time-sensitive and will fail if the generating server's clock is significantly out of sync with AWS.

Solution: For Retool Cloud, this is handled by Retool. For self-hosted Retool, ensure NTP is configured and your server time is synchronized. Check server time drift with `timedatectl status` on Linux. If drift exceeds a few minutes, S3 will reject presigned URLs. Additionally, verify that the Expiration value in your Retool presigned URL query is set in seconds (not milliseconds) — 3600 = 1 hour.

Best practices

  • Create a dedicated IAM user for Retool with the minimum required S3 permissions scoped to specific bucket ARNs, never using root account credentials or overly permissive admin policies.
  • Organize S3 uploads with meaningful key prefixes that include context like uploader email, date, or project ID — this makes programmatic listing and filtering much more efficient than flat bucket structures.
  • Always generate presigned URLs on demand rather than making S3 objects publicly accessible — this ensures access control remains enforced even after employees leave or permissions change.
  • Use the dedicated S3 Uploader component for end-user file uploads rather than building custom upload logic via the REST API, as it handles multipart uploads, retry logic, and progress indication automatically.
  • Store file metadata (uploader, upload timestamp, business tags, record associations) in a Retool Database or PostgreSQL table at upload time, enabling fast queries that S3's ListObjects cannot support natively.
  • Set appropriate S3 lifecycle rules on your bucket (via the AWS console) to automatically archive or delete old files — Retool does not manage S3 object lifecycle, so this must be configured in AWS directly.
  • For Retool Cloud connecting to buckets in firewalled VPCs or with IP-restricted bucket policies, whitelist Retool's published IP ranges or configure IAM role-based cross-account access instead of embedding long-lived access keys.

Alternatives

Frequently asked questions

Does Retool's S3 integration support uploading files larger than a few MB?

Yes. Retool's S3 Uploader component handles multipart uploads for large files automatically. For extremely large files (>100 MB), the upload may take time depending on the user's connection speed. There is no hard limit in Retool, but S3 itself requires multipart upload for files over 5 GB. The programmatic Upload File query type also handles standard uploads — for very large files via the query approach, ensure your Retool query timeout is configured appropriately (Settings → Resource → Advanced).

Can I connect Retool to S3-compatible storage services like MinIO, Backblaze B2, or Cloudflare R2?

Partially. Retool's native S3 connector targets AWS S3 specifically. For S3-compatible services that support the AWS S3 API (MinIO, Backblaze B2), you can sometimes use the native connector by pointing it at the compatible endpoint — but this is not officially supported by Retool. The more reliable approach is to connect S3-compatible services via a REST API resource using the service's own API endpoint. Backblaze B2, for example, has a native Retool connector (see the Backblaze B2 integration page).

How do I restrict the S3 Uploader to specific file types?

In the S3 Uploader component properties panel, set the 'Allowed File Types' field to a comma-separated list of MIME types or file extensions (e.g., .pdf,.docx or image/png,image/jpeg). Users attempting to upload disallowed file types will see an error in the uploader UI. Note that this is a client-side restriction — for strict enforcement, also validate file types server-side in a Retool Workflow or via S3 bucket policies.

Can multiple Retool apps share the same S3 resource?

Yes. Resources in Retool are organization-level objects, not app-level. Once you create an AWS S3 resource, all Retool apps in your organization can use it in their queries. You can also create multiple S3 resources pointing to different buckets or AWS accounts, and any app can reference any resource its users have access to.

Is it safe to use Retool Cloud with a private S3 bucket?

Yes, with proper IAM configuration. Retool Cloud proxies all S3 requests through Retool's servers, so your bucket never needs to be publicly accessible. Configure your S3 bucket policy to allow access only from Retool's published IP ranges, or use IAM role assumption with a cross-account trust policy granting Retool's AWS account access to your bucket. Never make your bucket public just to make it work with Retool.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Integrations are where projects stall

We wire Retool integrations like this one every week — auth, webhooks, edge cases included. Fixed-price builds from $13K, delivered in 6–10 weeks.

Talk to an integration engineer

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.