Autologin
Autologin turns a 1Password service account into a ready-to-use Authenticated Profile with a single request. You give it a service account and a profile name; Browserless opens a session, signs in to your sites using the credentials from your vault, and saves the logged-in state as a profile you can reuse everywhere with ?profile=<name>.
It automates the "log in once, then reuse a profile" flow you would otherwise script by hand with Browserless.loadSecret + Browserless.saveProfile — the whole sign-in is driven for you, and as with all 1Password credential filling the secret values never reach your code.
Use Autologin when you just want a logged-in profile and don't want to write the login steps yourself. Use loadSecret directly when you need fine-grained control over the sign-in flow inside your own automation. Both resolve secrets from the same service account.
- A Browserless API token (available in your account dashboard)
- A 1Password service account already connected to your API token
- Login items in the connected vault, each with a website URL and a username/password (add a one-time-password field for sites with TOTP-based MFA)
How it works
You send one request naming a service account and a profile name. Browserless then runs the login server-side:
- Open a session — Browserless starts a stealth browser session with the service account authorized, and signs in from a residential IP so the login isn't treated as datacenter traffic.
- Discover targets — it reads the Login items in the connected vault. Each item's website field is the origin to sign in to, and its username/password (and one-time-password, if present) are the fields to fill. Pass
allowedDomainsto log in to only a subset. - Sign in — for each site, an automated login agent navigates to the login page and fills the credentials by reference, exactly like
loadSecret: the value is resolved from 1Password and typed inside the session, and is never returned to your code, logged, or captured. - Save a profile — once a site is signed in, Browserless captures the session's authenticated state (cookies,
localStorage,IndexedDB) into an Authenticated Profile with the name you chose — the same captureBrowserless.saveProfileperforms.
The request returns immediately with a taskId; the login runs in the background. You poll the task for live progress and the final result.
The saved profile contains the signed-in cookies and storage — not your 1Password credentials. Reusing it replays that state; no secret is filled (or resolvable) from a session started with ?profile=<name>.
Starting an autologin
- Dashboard
- API
Open Profiles
Go to Profiles in the dashboard sidebar. Under 1Password Service Accounts, find the service account you want to sign in with — its vault must hold the Login items for the sites you want.
Create a profile
Click Create profile on that service account. In the Create profile dialog, set a Profile name (this is what you'll pass as
?profile=) and pick the Sites to log into — every discovered site is selected by default; uncheck any you want to skip.For sites that email a login code, choose an Email OTP inbox for each site, or use Apply one inbox to all sites and then override individual sites. Leave it at None for the existing username/password and TOTP flow. The inbox is a separate Login item containing the mailbox's IMAP credentials; it does not need a website URL. See inbox setup. The picker lists candidate items, not verified mailboxes; Gmail is tested and other IMAP providers are best-effort.
Start and copy the connect URL
Start it and watch each site sign in, with a live status line. On success the dialog shows a connect URL you can copy (a session URL with
?profile=<name>), and the profile appears under Authenticated Profiles, ready to reuse.
Create the task with a name for the resulting profile and the integrationId to sign in with. allowedDomains is optional — omit it to sign in to every Login item in the service account, or pass a subset of its origins.
curl -X POST "https://production-sfo.browserless.io/integrations/onepassword/profile?token=YOUR_API_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{
"name": "acme-prod",
"integrationId": "op_int_0a1b2c3d4e5f6a7b8c9d0e1f",
"allowedDomains": ["https://app.example.com"]
}'
The response is the task handle — poll it to follow progress:
{
"taskId": "autologin_eef23c512148b7198564ff49"
}
name— the profile name to create; reused later as?profile=<name>. Must be unique for your token.integrationId— the service account to sign in with (from its service-account record).allowedDomains— optional subset of the service account's origins; every value must be one of the service account's login origins.
To enable emailed codes, add an optional emailOtp array to the create request:
{
"emailOtp": [
{ "origin": "https://app.example.com", "vault": "Acme", "item": "Login inbox" }
]
}
Use the vault and item names returned in inboxCandidates by GET /integrations/onepassword/autologin/form?integrationId=...&token=.... Only item identities and labels are returned, never credential values. Each selected inbox must belong to that integration and contain username/password fields; each origin must be a selected login target. Invalid selections return 400 before a task starts. Omit emailOtp to retain the existing behavior.
Starting a second autologin for a name that's already in flight returns the existing taskId instead of starting a duplicate — polling either way follows the same task.
Recovering an existing profile
Use recovery when a saved login has expired or stopped working. Recovery signs in again and refreshes the existing profile without changing its name or ID. Only successfully recovered sites replace their saved state; unselected or failed sites keep their previous state. You don't need to delete the profile first.
Recover from the dashboard
- Open Profiles and find the saved profile under Authenticated Profiles. Open its actions menu and choose Recover with autologin.
- Choose a 1Password integration. Only login targets matching sites already captured in this profile are offered. Uncheck any sites you don't want to recover.
- For sites that email a login code, select an Email OTP inbox per site, or use Apply one inbox to all sites and override individual choices. Choose the integration and inboxes for each new recovery run; the profile doesn't remember the choices used to create it. None leaves email OTP disabled for that site. See inbox setup for the required IMAP credentials.
- Set optional Proxy settings if needed, then click Start recovery. Watch the live rationale and per-site results.
You can close the dialog and choose View recovery progress from the same profile's actions menu to reopen the current task. This progress view is retained while you stay on the Profiles page, not across navigation or a page reload. If status checks stop, Retry status reconnects to the same task instead of starting another recovery.
Recover through the API
Send the existing profile's name with recover: true to the same endpoint. Choose an integration that can sign in to its captured sites. Replace the example name, integration ID and inbox references with your own values.
curl --request POST \
--url "https://production-sfo.browserless.io/integrations/onepassword/profile?token=YOUR_API_TOKEN_HERE" \
--header "Content-Type: application/json" \
--data '{
"name": "acme-prod",
"integrationId": "op_int_0a1b2c3d4e5f6a7b8c9d0e1f",
"recover": true,
"allowedDomains": ["https://app.example.com"],
"emailOtp": [
{ "origin": "https://app.example.com", "vault": "Acme", "item": "Login inbox" }
]
}'
Response:
{
"taskId": "autologin_eef23c512148b7198564ff49"
}
Poll this task using the progress endpoint. To discover eligible origins and inboxes before starting, call GET /integrations/onepassword/autologin/form with integrationId, profileName, and token query parameters. URL-encode their values. Use its domains and inboxCandidates to build the request.
allowedDomains narrows recovery to selected captured sites; it can't add a new site to the profile. Omit emailOtp for sites that don't need emailed codes. Recovery uses the same inbox validation and server-side code filling as profile creation.
Tracking progress
Poll the task by id. It reports its overall state, a live currentRationale (what the agent is doing right now), and the per-domain progress.
curl "https://production-sfo.browserless.io/integrations/onepassword/profile/autologin_eef23c512148b7198564ff49?token=YOUR_API_TOKEN_HERE"
{
"taskId": "autologin_eef23c512148b7198564ff49",
"state": "success",
"currentRationale": null,
"profileId": "profile_9b5c6923a7d631cdee36e259",
"profileName": "acme-prod",
"domains": [
{ "origin": "https://app.example.com", "status": "success" }
],
"createdAt": "2026-06-18T12:00:00.000Z",
"updatedAt": "2026-06-18T12:02:00.000Z"
}
state moves through:
| State | Meaning |
|---|---|
pending | Accepted, not started yet. |
running | Signing in; watch currentRationale and domains[].status. |
success | At least one domain signed in and the profile was saved — profileName is ready to reuse. |
failed | The task ended without a saved profile — see errorCode / errorMessage. |
Each entry in domains carries its own status: pending (not reached), active (currently attempting), tried (moved past, outcome pending), then the terminal success or failed (with an error).
- Node
- curl
const BASE = 'https://production-sfo.browserless.io';
const TOKEN = 'YOUR_API_TOKEN_HERE';
// Use the taskId returned by your create or recovery request.
const taskId = 'YOUR_TASK_ID_HERE';
// Poll until it settles.
let task;
do {
await new Promise((r) => setTimeout(r, 4000));
task = await fetch(`${BASE}/integrations/onepassword/profile/${taskId}?token=${TOKEN}`).then((r) => r.json());
console.log(task.state, task.currentRationale ?? '');
} while (task.state === 'pending' || task.state === 'running');
if (task.state === 'success') {
console.log('Profile ready:', task.profileName); // reuse via ?profile=<name>
} else {
console.error('Autologin failed:', task.errorCode, task.errorMessage);
}
TASK=autologin_eef23c512148b7198564ff49
# Re-run until "state" is "success" or "failed".
curl -s "https://production-sfo.browserless.io/integrations/onepassword/profile/$TASK?token=YOUR_API_TOKEN_HERE"
Using the saved profile
On success, the profile named <name> is a normal Authenticated Profile. Reuse it on any session by adding ?profile=<name> — the browser loads its cookies and storage before navigating, so the page opens already signed in.
import puppeteer from 'puppeteer-core';
const browser = await puppeteer.connect({
browserWSEndpoint:
'wss://production-sfo.browserless.io/chromium?token=YOUR_API_TOKEN_HERE&profile=acme-prod',
});
const page = await browser.newPage();
await page.goto('https://app.example.com'); // already logged in
Because a reused profile fills no secret, the session isn't locked down — screenshots, PDFs, and page reads all work normally. When credentials rotate or the session expires, recover the existing profile to refresh its saved state.
Security
Autologin inherits the 1Password security model:
- Secrets stay server-side — credentials are resolved from 1Password and typed inside the session; they're never returned to your code, logged, or captured.
- Origin safety — credentials are only ever typed into public
https://origins;http://and private/internal addresses are always refused. If the service account sets an allow-list, sign-ins are limited to it (by default, with no list, any public https origin is allowed);allowedDomainson the request can narrow a run further. - Locked-down capture during login — once a credential is filled, the sign-in session blocks screenshots, PDFs, and page reads, tears down live URLs, aborts any in-progress screen recording, and scrubs the filled values from logs and the session replay — so the typed value can't leak. The saved profile is captured through the same trusted path.
- Audit log — each credential resolve is recorded (reference, origin, outcome) — never the value.
- Token-scoped — tasks and profiles are scoped to your API token; other tokens can't see or reuse them.
Failure modes
If the request is rejected, it returns an error before a task starts:
| Status | When |
|---|---|
400 | name or integrationId missing, allowedDomains isn't an array of origins, an origin isn't an eligible login target, a profile with that name already exists and recover isn't true, or an emailOtp entry references an invalid inbox, an inbox missing the required IMAP username/password fields, or an origin not selected for this run. |
404 | The integrationId is unknown, expired, or unreachable, or the profile to recover doesn't exist for this API token. |
503 | The service account or 1Password is temporarily unavailable — retry. |
Once running, a task that can't finish ends in state: "failed" with an errorCode:
errorCode | Meaning | What to do |
|---|---|---|
AllDomainsFailed | Every targeted site failed to sign in — check each domains[].error. | Verify the Login items resolve and the credentials/selectors are valid; retry. |
AutologinTimeout | The sign-in didn't complete within the time budget. | Retry; a slow site or an extra step (MFA, interstitial) can exceed the budget. |
AgentError | The login couldn't be completed or the profile couldn't be saved. | Retry; if it persists, contact support. |
Per-domain error values reuse the loadSecret failure codes (for example CredentialNotResolved, DomainNotAllowed, SelectorNotFound) so you can see exactly why a site didn't sign in.
When no fresh emailed code arrives, the affected domain carries errorCode: "EmailOtpTimeout"; the dashboard displays Email code didn't arrive. This differs from an unsupported MFA challenge. Check the mailbox credentials and delivery, then retry. Other domains can still succeed and produce a profile.
FAQ & Troubleshooting
Why does recovery ask me to re-authenticate manually for an emailed code?
Select an Email OTP inbox for that site before starting recovery, or include its inbox mapping in emailOtp when using the API. Having configured an inbox during profile creation doesn't configure later recovery runs. Without an inbox selection, Browserless can't retrieve the emailed code. SMS, push approvals, and other unsupported challenges still need manual re-authentication.
If the result says Email code didn't arrive (EmailOtpTimeout), check the selected mailbox's IMAP credentials and code delivery instead. If recovery reports SharedCookieConflict, no saved state was changed: replacing a shared cookie would affect an unselected or failed site. Finish re-authentication manually rather than deleting the profile.
How is Autologin different from loadSecret?
loadSecret fills one referenced field into a selector you choose, inside your own automation. Autologin drives the entire sign-in for you across the service account's Login items and saves a reusable profile at the end. Both resolve secrets from the same service account and never expose the value.
Does it handle multi-factor authentication?
If the Login item has a one-time-password (TOTP) field, autologin can use it. For emailed codes, select an Email OTP inbox: the agent triggers the site's send-code step, then fills the code server-side using the distinct emailOtp credential. It never sees the code value. SMS codes and push approvals still require manual completion. You can also drive emailed-code filling yourself with loadSecret.
The profile name already exists — what happens?
A normal create request is rejected with 400. Use a new name to create a separate profile. To refresh the existing profile, choose Recover with autologin in the dashboard or send its name with recover: true. Recovery preserves the profile's name and ID; deletion isn't required.
Can I sign in to only some of the service account's sites?
Yes. Pass allowedDomains with the subset of origins you want. Each value must be one of the service account's login origins.