namestringrequired1 to 60 characters, unique on the account (case-insensitive). "Default" is reserved.
RUN
A profile run never sees your other logins, and its sign-ins never leak into Default.
Add logins by signing in inside a cloud run, or import a cookie file.
Each profile keeps an exit location, pinned from its first sign-in if you set none.
Two kinds
In the Cloud app, the Logins chip under the composer switches profiles: create, rename, delete, and set the account default there. The pick is remembered in that browser. Picking a profile with a location moves the location chip to it.
REST
https://mcp.rtrvr.ai/v1/profiles. Use the same API key as /agent and /scrape (or an MCP OAuth token). Responses list names only: cookie values are never returned, and there is no export.| Request | Body | Returns |
|---|---|---|
POST /v1/profiles | { name, location?, proxyId?, makeDefault? } | 201 { profile } |
GET /v1/profiles | — | { profiles, defaultProfileId } |
GET /v1/profiles/{id} | — | { profile, sites } (names only) |
PATCH /v1/profiles/{id} | { name?, location?, proxyId?, makeDefault? } | { profile } |
DELETE /v1/profiles/{id} | — | { deleted, sitesDeleted } |
PUT /v1/profiles/{id}/state | a login file (see Import) | { imported, sites, skipped, ignored } |
DELETE /v1/profiles/{id}/sites/{site} | — | { site, deleted, domains } |
namestringrequired1 to 60 characters, unique on the account (case-insensitive). "Default" is reserved.
locationobject | nullWhere runs on this profile exit: {country, region?, city?} in the same shape as settings.proxyConfig.location. null clears it.
proxyIdstring | nullThe id of a proxy saved in Cloud Settings → Proxy Config. Runs on the profile use it instead of the managed proxy, so they keep the same IP.
makeDefaultbooleantrue makes this the account default: API and MCP runs that name no profile use it. false on the current default goes back to Default.
curl -X POST https://mcp.rtrvr.ai/v1/profiles \
-H "Authorization: Bearer rtrvr_your_api_key" \
-H "Content-Type: application/json" \
-d '{"name": "Client A", "location": {"country": "US", "region": "NY", "city": "New York"}}'Use it
profile (an id or the exact name, or "default") to POST /agent, POST /scrape, or the MCP cloud_agent and cloud_scrape tools.curl -X POST https://api.rtrvr.ai/agent \
-H "Authorization: Bearer rtrvr_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"input": "Download last month's invoices",
"urls": ["https://billing.example.com/invoices"],
"profile": "Client A"
}'{
"name": "cloud_agent",
"arguments": {
"user_input": "Reply to the newest support ticket",
"urls": ["https://support.example.com"],
"profile": "Client A"
}
}profilestringOmit it to use the account default profile (Default when none is set). A run that continues an earlier one stays on that run's profile.
session_sourceMCP onlyStill works for one device's logins or "none". Pass profile or session_source, not both.
settings.proxyConfigobjectA route the request names wins over the profile's location or saved proxy.
The MCP result's logins names the profile a run used. Schedules run on the profile their saved request names, never on a later account default.
Bring your logins
PUT /v1/profiles/{id}/state, or drop it on the Logins chip's Import box in the Cloud app. Each site in the file replaces that site's saved logins in the profile; other sites stay. Add "replace": true to clear every other site first.# A Playwright storageState file
curl -X PUT https://mcp.rtrvr.ai/v1/profiles/PROFILE_ID/state \
-H "Authorization: Bearer rtrvr_your_api_key" \
-H "Content-Type: application/json" \
--data-binary @state.json
# A cookies.txt file
curl -X PUT https://mcp.rtrvr.ai/v1/profiles/PROFILE_ID/state \
-H "Authorization: Bearer rtrvr_your_api_key" \
-H "Content-Type: text/plain" \
--data-binary @cookies.txt
# A Cookie header: say which page it was sent to
curl -X PUT https://mcp.rtrvr.ai/v1/profiles/PROFILE_ID/state \
-H "Authorization: Bearer rtrvr_your_api_key" \
-H "Content-Type: application/json" \
-d '{"content": "Cookie: session=...; csrftoken=...", "url": "https://app.example.com/"}'| Format | How to get it |
|---|---|
Playwright storageState JSON | await context.storageState({ path: "state.json" }) after signing in (snippet below). Its localStorage is not imported; the response says how many origins were left out. |
| Cookie-Editor or EditThisCookie JSON | Open the extension on the signed-in site and export as JSON. |
Netscape cookies.txt | A "Get cookies.txt" style exporter, curl -c, or yt-dlp --cookies. #HttpOnly_ lines are kept as HttpOnly. |
| DevTools "Copy as cURL" | Chrome DevTools → Network → reload the signed-in page → right-click its first request → Copy → Copy as cURL (bash or cmd). Paste it into "Paste from DevTools". |
A Cookie: header + URL | The request's Cookie header from DevTools, with the page URL it was sent to. |
// After signing in with Playwright:
await context.storageState({ path: "state.json" })
// Or sign in by hand once, then save the state:
const browser = await chromium.launch({ headless: false })
const context = await browser.newContext()
const page = await context.newPage()
await page.goto("https://app.example.com/login")
// … sign in in the window that opened …
await context.storageState({ path: "state.json" })Limits: 2 MB per file, 100 sites, 300 cookies per site, 30 imports per hour per account. Expired cookies are skipped. Each site gets a sign-in check from its cookie names, so you see right away which sites carry a login.
Look like the same visitor
Kept apart
YOUR NEXT RUN