Connect Amazon S3 to webQsee with per-user credentials
The complete walk-through for teams: every member gets their own AWS IAM user, their own private folder and a shared space, with permission checks enforced at the storage layer, not just in the UI.
Estimated time: 25–35 min · Last reviewed: 2026-05 · Difficulty: Intermediate
Before you start
- webQsee installed in Chrome or Edge, get it here
- Active webQsee Professional or Team plan (Cloud Gallery requires this), see pricing
- A working email address that you can use to sign up for AWS (a credit card is required by AWS even on the free tier, but webQsee usage typically stays well within free limits for small teams)
- Your webQsee team set up with the team members you want to onboard, if you don't have one yet, see Create and manage multiple webQsee teams
webQsee uploads captured screenshots, screencasts, behavior reports and snapshots directly to your S3 bucket from the browser extension. Our servers only see metadata. That means you stay in control of the data, and you pay AWS, not us, for storage.
This tutorial sets up the multi-user pattern: one shared webqsee-admin policy for power users, plus a restricted webqsee-user policy that uses an IAM tag (webqsee-user-id) so each team member can only write into their own /private/<their-id>/ folder while still sharing access to /shared/ and read-only /protected/.
Looking for the lighter setup (one shared IAM user, no per-user separation)? See Simplified S3 integration instead.
1. Create an AWS account
Open the AWS sign-up page
Navigate to aws.amazon.com/free and click Create an AWS Account. Use a long-lived email address, this becomes the AWS root account, which you should rarely use afterwards.
Sanity check: You should land on the "Sign up for AWS" form with fields for Root user email address and AWS account name.Complete the AWS sign-up flow
Fill in contact details, choose Personal or Business, enter payment info, confirm the SMS/voice verification code and pick the Basic Support, Free plan. AWS may take a minute or two to activate the account.
Sanity check: You see "Congratulations" / "Your AWS account is ready" and the button "Go to the AWS Management Console" is enabled. Sign in as the root user.Set the console region
In the top-right of the AWS Console choose the region you want your data to live in, for European GDPR-friendly storage that's typically
eu-central-1(Frankfurt). Write the region code down; you'll need it later.Sanity check: The region selector in the top-right shows your chosen region (e.g. "Europe (Frankfurt) eu-central-1").
2. Create the webqsee-admin IAM policy
This policy grants the operations webQsee needs to upload, read, replace and delete artifacts across all three folder areas of the bucket: /shared/, /protected/ and /private/. Admins also need ListBucket on those prefixes.
Open the IAM Policies page
In the AWS Console search bar type IAM and open the IAM service. In the left sidebar click Policies, then Create policy. Switch to the JSON tab.
Sanity check: You're in the IAM → Policies → Create policy editor and see an empty JSON editor on the right.Paste the admin policy JSON
Replace the placeholder content with the JSON below. Note: this policy targets a bucket literally named
webqsee, if you intend to use a different bucket name, replace every occurrence ofwebqseein the ARNs below first.{ "Version": "2012-10-17", "Statement": [ { "Sid": "AdminListBucket", "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetBucketLocation", "s3:GetBucketCors" ], "Resource": "arn:aws:s3:::webqsee", "Condition": { "StringLike": { "s3:prefix": [ "shared/*", "protected/*", "private/*", "shared/", "protected/", "private/", "" ] } } }, { "Sid": "AdminFullObjectAccess", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:GetObjectTagging", "s3:PutObject", "s3:PutObjectTagging", "s3:DeleteObject", "s3:AbortMultipartUpload", "s3:ListMultipartUploadParts" ], "Resource": [ "arn:aws:s3:::webqsee/shared/*", "arn:aws:s3:::webqsee/protected/*", "arn:aws:s3:::webqsee/private/*" ] } ] }Sanity check: The JSON editor shows no red error indicators. Click Next: AWS validates the JSON and shows a "Review and create" page summarising the permissions (S3: GetObject, PutObject, DeleteObject, ListBucket, etc.).Name and save the policy
Set Policy name to
webqsee-admin(exact spelling matters; you'll match it later). Description: "webQsee Cloud Gallery, admin/full access to /shared, /protected, /private". Click Create policy.Sanity check: The policies list now containswebqsee-adminwith a "Customer managed" type label.
3. Create the webqsee-user IAM policy
This is the per-user policy. The clever bit is the IAM tag condition aws:PrincipalTag/webqsee-user-id: it injects the value of the tag webqsee-user-id that you attach to each IAM user into the policy at evaluation time. That means every user is granted write access only to the prefix /private/<their-own-id>/, even though all users share the same policy document.
Create another policy
IAM → Policies → Create policy → JSON tab.
Sanity check: You're back at the empty JSON editor, a fresh policy, not editing the admin one.Paste the user policy JSON
This grants read/write on
/shared/*, read/write on/private/${aws:PrincipalTag/webqsee-user-id}/*, and read-only on/protected/*.{ "Version": "2012-10-17", "Statement": [ { "Sid": "UserListBucketScoped", "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetBucketLocation", "s3:GetBucketCors" ], "Resource": "arn:aws:s3:::webqsee", "Condition": { "StringLike": { "s3:prefix": [ "shared/*", "shared/", "protected/*", "protected/", "private/${aws:PrincipalTag/webqsee-user-id}/*", "private/${aws:PrincipalTag/webqsee-user-id}/", "" ] } } }, { "Sid": "UserSharedReadWrite", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:GetObjectTagging", "s3:PutObject", "s3:PutObjectTagging", "s3:DeleteObject", "s3:AbortMultipartUpload", "s3:ListMultipartUploadParts" ], "Resource": "arn:aws:s3:::webqsee/shared/*" }, { "Sid": "UserPrivateReadWrite", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:GetObjectTagging", "s3:PutObject", "s3:PutObjectTagging", "s3:DeleteObject", "s3:AbortMultipartUpload", "s3:ListMultipartUploadParts" ], "Resource": "arn:aws:s3:::webqsee/private/${aws:PrincipalTag/webqsee-user-id}/*" }, { "Sid": "UserProtectedReadOnly", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:GetObjectTagging" ], "Resource": "arn:aws:s3:::webqsee/protected/*" } ] }Sanity check: The JSON validates without errors. Click Next and the review page lists four statements (UserListBucketScoped, UserSharedReadWrite, UserPrivateReadWrite, UserProtectedReadOnly).Name and save
Name:
webqsee-user. Description: "webQsee Cloud Gallery, per-user policy, write to own /private prefix, R/W /shared, R/O /protected". Click Create policy.Sanity check: Bothwebqsee-adminandwebqsee-usernow appear in the Customer managed policies list.
4. Create the two IAM groups
Create group
webqsee-adminIAM → User groups → Create group. Name:
webqsee-admin. In Attach permissions policies search forwebqsee-adminand tick it. Click Create group.Sanity check: The groupwebqsee-adminappears in the User groups list with 1 attached policy and 0 users.Create group
webqsee-userRepeat: Create group, name
webqsee-user, attach thewebqsee-userpolicy, save.Sanity check: Both groups now show in the list, each with 1 attached policy.
5. Add one IAM user per team member
Look up each member's webQsee user ID
In webQsee click the toolbar icon and open the main window. Go to Settings → Current User and Team. The field User ID shows a UUID-like string (e.g.
u_8f3c9a1e). Each member should send their own ID to you, or look at the team roster which lists them.Sanity check: You have a list of (display name → webQsee user ID) pairs for every team member who needs access.
Create the first IAM user
IAM → Users → Create user. Username: pick something recognisable, e.g.
alice-webqsee. Do not tick "Provide user access to the AWS Management Console", webQsee needs programmatic API access only. Click Next.Sanity check: You're on step 2 ("Set permissions") of the Create user wizard.Add the user to a group
Choose Add user to group. Tick
webqsee-userfor a regular team member, orwebqsee-adminif this person should manage the bucket. Click Next.Sanity check: The "Permissions summary" shows the group membership and the policy it carries.Tag the user with their webQsee ID critical
On the Tags (optional) step add a tag with Key
webqsee-user-idand Value equal to that person's webQsee user ID (e.g.u_8f3c9a1e). The case must match exactly, thewebqsee-userpolicy uses this tag to scope/private/access. Click Next → Create user.Sanity check: Open the new user, switch to the Tags tab: the row "webqsee-user-id = u_..." is present. Without this tag, the user cannot upload anything to their private folder.Generate the access key
Open the new user → Security credentials tab → Create access key. Use case: Application running outside AWS (it's a browser extension). Click through, optionally add a description tag.
Sanity check: AWS shows you the Access key ID (starts withAKIA) and the Secret access key exactly once.Securely deliver the credentials
Download the CSV or copy both values into your password manager. The secret cannot be recovered, if you lose it you have to delete the key and create a new one. Send each user their own pair using an end-to-end-encrypted channel (1Password sharing, Bitwarden Send, signed PGP email, etc.).
Sanity check: The recipient confirms they have received both the Access Key ID and the Secret. Close the AWS dialog only after confirmation.Repeat for every team member
One IAM user per person, with the matching
webqsee-user-idtag and one access key each.Sanity check: IAM → Users now shows every team member as an Active user, each in eitherwebqsee-adminorwebqsee-usergroup, each with the right tag.
6. Create the S3 bucket
Open the S3 console
Console search → S3 → Create bucket. Confirm in the top-right that you're still in the region you decided on (e.g.
eu-central-1).Sanity check: You're on the "Create bucket" form and the region matches your choice.Name the bucket
Use the name your policies expect:
webqsee. If that global name is already taken, use something unique (e.g.webqsee-acme-2026) and update the ARNs in both IAM policies to match.Sanity check: The "Bucket name" field shows green / valid, no "already exists" or "invalid name" warning.Block all public access
Leave Block all public access ticked. webQsee never makes objects public; it uses authenticated requests from the extension using each user's access key.
Sanity check: All four "Block public access" sub-checkboxes are ticked.Versioning, encryption, ACLs
Bucket versioning: Disabled (versioning makes deletions soft, not what you want for screen-recordings that may be confidential). Default encryption: SSE-S3 (AES-256), free and recommended. Object ownership: ACLs disabled.
Sanity check: The review summary shows Versioning: Disabled, Encryption: SSE-S3, Public access: Blocked.Create the bucket
Click Create bucket.
Sanity check: A green toast says "Successfully created bucket 'webqsee'" and the bucket appears in the S3 bucket list with your region next to it.
7. Configure CORS on the bucket
The webQsee extension is loaded from chrome-extension:// and view.webqsee.com, so the bucket must permit cross-origin uploads and reads from these origins.
Open the bucket's Permissions tab
S3 → click your bucket → Permissions tab → scroll to Cross-origin resource sharing (CORS) → Edit.
Sanity check: A JSON editor opens, currently empty or with placeholder content.Paste the CORS config
[ { "AllowedOrigins": [ "https://view.webqsee.com", "https://app.webqsee.com", "chrome-extension://*" ], "AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"], "AllowedHeaders": ["*"], "ExposeHeaders": ["ETag", "x-amz-request-id", "x-amz-version-id"], "MaxAgeSeconds": 3000 } ]Click Save changes.
Sanity check: A green toast "Successfully edited CORS" appears, and the saved CORS block shows the AllowedOrigins above.
8. Configure webQsee Cloud Gallery
Open Cloud Gallery settings
In webQsee open the main window (Alt+A or via the popup), go to Gallery tab, click Cloud Gallery, then Edit Settings.
Sanity check: A settings panel opens with two sections: Team-wide and Personal.Set the team-wide values (admin only)
These are saved on the webQsee server for the whole team:
- Storage Type:
S3 compatible storage, KEY-Auth - Authentication mode:
Per-user credentials (multi-user) - Bucket name:
webqsee(or your custom name) - Connection settings:
{ "region": "eu-central-1" }
Click Save team settings.
Sanity check: A toast "Team cloud settings saved" appears; the panel now reads "Awaiting your personal credentials".- Storage Type:
Enter your personal credentials
In the Personal section paste your own Access Key ID and Secret access key. They are stored encrypted inside the extension only, not transmitted to webQsee servers. Click Save personal credentials.
Sanity check: A green indicator "Cloud Storage connected ✓" appears at the top of the Cloud Gallery panel.Ask every team member to do the same
They only need to enter their personal Access Key ID and Secret, the team-wide settings come down automatically.
Sanity check: Each member sees "Cloud Storage connected ✓" in their own webQsee installation.
Final sanity check
Open webQsee → Gallery → Cloud Gallery. You should see "Cloud Storage connected ✓". Now record a quick screenshot, right-click it in the local gallery and choose Upload to Cloud → Private. Within a few seconds it should appear under the Cloud Gallery's Private tab.
If you get a 403 in the browser console: re-check that the bucket name in your IAM policy ARNs matches the actual bucket name (step 6 vs step 2/3), and confirm the IAM user has the webqsee-user-id tag (step 5). If you get a CORS error, re-apply step 7.
Troubleshooting
- CORS error in browser console ("No 'Access-Control-Allow-Origin' header is present"): the bucket's CORS configuration is missing or wasn't saved. Re-apply step 7 and click Save changes; AWS sometimes silently rejects malformed JSON.
- 403 Forbidden on PUT to
/private/…: the IAM user is missing thewebqsee-user-idtag, or the tag value does not match the path the extension is uploading to. Re-check step 5 step 4 and ensure the tag equals the webQsee user ID exactly (case-sensitive). - 403 Forbidden on any PUT: the policy ARN does not match the bucket name. The policy uses
arn:aws:s3:::webqsee/…but the bucket might actually be calledwebqsee-acme-2026. Edit the customer-managed policies and update all ARNs. - SignatureDoesNotMatch: the secret access key was copied incorrectly (an extra space, missing character) or expired. Generate a new key in IAM and re-enter it in webQsee.
- NoSuchBucket: the bucket name in webQsee's team-wide settings has a typo, or the bucket lives in a different region than the
regionfield in the Connection settings JSON. - RequestTimeTooSkewed: the machine clock is more than 15 minutes off UTC. Re-sync the OS clock.
- Listing works but downloads of
/protected/403: the user is in thewebqsee-usergroup, which has read-only on/protected/. That's correct, uploads to/protected/are reserved for admins.
Related tutorials
Simplified S3 integration
One shared IAM user for solo users and small teams, less granular but quicker to set up.
Open tutorialMigrate from simplified to multi-user
Already running on the simple setup? This guide shows the safe transition path.
Open tutorialOne bucket, multiple teams
Share a single bucket across several webQsee teams using prefix-based isolation.
Open tutorialOne bucket per team
The stricter alternative, harder isolation boundaries at the cost of more buckets to manage.
Open tutorialStop guessing. Start webQseeing.
Add webQsee to Chrome or Edge in one click. Most features are free, forever, no signup needed. Upgrade only if your team needs cloud sharing, S3 storage and Pro-grade tooling.
Works in Chrome 103+, Edge 103+ and most Chromium-based browsers. Install instructions.