Docs
Dashboard
Guides / AccountBeta

Plans and features

What your plan controls: limits and feature switches, which features are paid, the 402 feature_not_in_plan error, how to check your plan from code, and suspended projects.

Every Boxline organization is on a plan, and every project in it runs on that plan. The plan sets two things: limits, such as how many sessions can run at once, and feature switches, such as whether the platform’s residential proxies are included.

This page lists both, explains the error you get when a feature is not in your plan, and shows how to check your plan from code. Prices are on the pricing page. How an organization’s projects share its plan is on Organizations, projects and team members.

Limits

Your plan’s limits are in GET /v1/auth/me as project.limits. For the caps below, null means no limit. Every refusal of your plan answers with status 402: feature_not_in_plan, spend_limit or plan_limit.

These are the plan’s limits, and only we change them. You can also set your own monthly spending limit for the organization and for each project. It covers all usage and uses the same code, 402 spend_limit. See Credit and spending limits.

The plan is the organization’s, so some limits are shared. Running sessions, model spend, proxy data, CAPTCHA solves and web searches are added up over all the organization’s projects: a second project does not give you a second allowance. The refusal says “this organization”. The counts a project keeps (credentials, browser profiles, extensions, webhook endpoints, tasks and schedules) stay per project. A project can also have a lower cap on its own running sessions, concurrencyCap.

limits fieldWhat it capsWhen you reach it
concurrencySessions running at the same time, in all the organization’s projects together. A project may have a lower cap of its own (project.concurrencyCap).429 concurrency_limit. See A cap for one project.
maxTimeoutSecondsHow long one session can last: its timeout, on create and when you change it with Update a session.402 plan_limit
modelSpendCapUsdModel spend on Boxline’s keys per calendar month (UTC), over all the organization’s projects: agent runs, extract and plain-English steps. Runs on your own model key do not count.402 spend_limit until the 1st
proxyGbPerMonthData through the platform’s residential and datacenter proxies per calendar month. Your own proxy does not count.402 spend_limit until the 1st. See Proxies.
captchaSolvesPerMonthAutomatic CAPTCHA solving attempts per calendar month. 0 means none.A person is asked instead. See CAPTCHAs.
searchesPerMonthWeb searches included per calendar month (UTC).Each 1,000 more costs extraSearchesPer1000Usd. See Search.
extraSearchesPer1000UsdThe price of 1,000 searches beyond the allowance. null means no searches beyond it.402 plan_limit until the 1st, when it is null.
webhookEndpointsHow many webhook endpoints the project can have.A new endpoint gets 402 plan_limit. See Webhooks.
tasksHow many tasks the project can keep: 1 on Free, no plan limit on the others (1,000 per project at most).A new task gets 402 plan_limit. See Tasks.
schedulesTasks with a schedule switched on: none on Free, 5 on Hobby, 50 on Startup, no limit on Scale.Switching one on gets 402 plan_limit; after a downgrade, times are skipped. See Tasks.
maxCredentialsHow many credentials (passwords and secrets together) the project can keep: 200 on every plan.A new credential gets 402 plan_limit. See Credentials.
maxProfilesHow many browser profiles the project can keep: 10 on Free, 100 on Hobby, 500 on Startup, 2,000 on Scale.A new profile gets 402 plan_limit. See Browser profiles.
maxProfileBytesHow much saved state (cookies and local storage) all profiles hold together: 50 MB on Free, 1 GB on Hobby, 5 GB on Startup, 20 GB on Scale. One profile holds at most 16 MB.A new profile gets 402 plan_limit; a save that would pass the total is skipped. See Browser profiles.
retentionDaysHow long a stopped session keeps its saved browser and files, its recording, logs and agent-run steps: 7 days on Free, 30 on Hobby and Startup, 90 on Scale. Counted from the day it stopped.The session is deleted (deleteReason: "retention"). Its deletesAt says when. See Lifecycle.

limits also has the plan’s name, its monthly priceUsd (null for custom pricing) and includedUsd, the usage included each month. For the session limits of each plan, see Sessions.

Features

A feature is a switch: your plan includes it or it does not. The API uses the names in the first column. GET /v1/pricing returns the same labels.

API nameLabelWhat needs itFree plan
shellShell sessionsshell: true on a session, or in the session of an agent run or task.Included
profilesBrowser profilesPOST /v1/profiles, and starting a session (or an agent run or task, in its session) with profile.Included
recordingSession recordingsReplay frames. Without it, sessions are not recorded, and recordSession: true fails.Included
realisticBrowserBrowser mode (clock and language)Sessions with browser.mode: "realistic", a locale or a timezone: on create, in Update a session, and in the session of agent runs.Paid plans
residentialProxyResidential proxiesA residential proxy (or proxy: true) on sessions, in Update a session, in agent runs and in the quick APIs.Paid plans
datacenterProxyDatacenter proxiesA datacenter proxy, in the same places.Paid plans
customProxyYour own proxyA custom proxy, in the same places.Included
captchaSolvingAutomatic CAPTCHA solvingcaptcha: "solve" on create, in Update a session, and in the session of agent runs.Paid plans
agentRunsAgent runsPOST /v1/agent/runs.Included
stepsPlain-English stepsstep actions in POST /v1/sessions/:id/browser/actions.Included
extractExtractPOST /v1/extract.Included
quickApisFetch, screenshot and PDFPOST /v1/fetch, /v1/screenshot and /v1/pdf.Included
crawlCrawlPOST /v1/crawls.Included
extensionsChrome extensionsPOST /v1/extensions, and extensions on a session (also in the session of an agent run or task).Paid plans
webSearchWeb searchPOST /v1/search and the agent’s web_search tool.Included
loginDetailsWebsite passwords with 2FA (password credentials)Creating a credential of type password, linking one to a profile, using one as %NAME.username%, %NAME.password% and %NAME.otp% or $NAME_PASSWORD, and the login action. Secrets are on every plan.Paid plans
platformModelsBoxline's model keysAI calls on the platform's own model keys. Without it (Free), agent runs, steps and extract run on your own model keys only, or get 402 feature_not_in_plan. See Your own model keys.Paid plans

By default, seven features are for paid plans only: the platform’s residential and datacenter proxies, browser mode, automatic CAPTCHA solving, Chrome extensions, password credentials (website passwords with 2FA), and Boxline's own model keys (Free runs AI on your own keys). Free has every other feature. Hobby, Startup and Scale have all of them.

Your own proxy works on every plan, Free included. See Your own proxy.

When a feature is not in your plan

A call that needs a feature your plan does not include fails with 402 feature_not_in_plan. The message names the plan and the feature.

Shell
curl -X POST https://api.boxline.dev/v1/sessions \  -H "x-api-key: $BOXLINE_API_KEY" \  -H "content-type: application/json" \  -d '{"browser": true, "proxy": {"type": "residential", "country": "US"}}'
Response (402)
{  "error": {    "code": "feature_not_in_plan",    "message": "the Free plan does not include residential proxies"  }}
  • The call fails before anything starts, so nothing is billed.
  • It is checked each time you make a call. A change with Update a session (PATCH /v1/sessions/:id) is checked against your plan at that moment.
  • Automatic CAPTCHA solving is checked again at every attempt. If your plan no longer includes it, a person is asked instead.
  • Retrying does not help. The call works once your plan includes the feature, or without the option that needs it.

In the SDKs it is a BoxlineError with status 402 and code feature_not_in_plan:

import { Boxline, BoxlineError } from "@boxline/sdk";const client = new Boxline(); // reads BOXLINE_API_KEY and BOXLINE_API_URLtry {  const session = await client.sessions.create({ browser: true, proxy: { type: "residential", country: "US" } });  await session.stop();} catch (err) {  if (err instanceof BoxlineError && err.code === "feature_not_in_plan") {    console.error(err.message); // "the Free plan does not include residential proxies"  } else {    throw err;  }}

Check your plan from code

GET/v1/auth/me returns your project with its plan’s limits, and limits.features has every feature as true or false. organization has the organization’s own summary (with an API key, its role is null: a key is not a member):

GET /v1/auth/me (excerpt)
"organization": {  "id": "…",  "name": "…",  "plan": "free",  "personal": true,  "suspended": null,  "role": null},"project": {  "id": "…",  "name": "…",  "plan": "free",  "orgId": "…",  "concurrencyCap": null,  "suspended": null,  "limits": {    "name": "Free",    "concurrency": …,    "maxTimeoutSeconds": …,    "captchaSolvesPerMonth": 0,    "features": {      "shell": true,      "residentialProxy": false,      "customProxy": true,      "captchaSolving": false,      …    }  },  "trajectories": { "enabled": true, "noticeSeenAt": null, "decidedBy": null }}

In TypeScript, client.hasFeature(name) answers for one feature. It calls GET /v1/auth/me each time, so when you check several, call client.me() once. The Python SDK has bx.me(), and no has_feature.

curl https://api.boxline.dev/v1/auth/me \  -H "x-api-key: $BOXLINE_API_KEY"

Check your plan when your program starts, not before every call. A call without the feature fails safely with feature_not_in_plan anyway.

Public plans

GET/v1/pricing is the public price table. It needs no API key. Besides the prices, it has:

FieldWhat it is
plansThe plans you can choose, each with its id, the same fields as limits above, and its features.
featuresEvery feature’s label by API name, for example "captchaSolving": "Automatic CAPTCHA solving".
Shell
# Which features does each public plan include?curl -s https://api.boxline.dev/v1/pricing \  | jq '.plans[] | {id, name, features: (.features | with_entries(select(.value)) | keys)}'

Prices, limits and allowances may change during the beta. Read them from this endpoint rather than copying numbers into your code.

Suspended organizations and projects

We may suspend an organization, for example for a breach of the acceptable-use rules in the Terms of Service. A suspension belongs to the organization, so it suspends every project in it. When that happens:

  • The running sessions of its projects are stopped (stopReason: "suspended").
  • API calls with a key of one of its projects, or a console login in it, get 403 project_suspended, with the reason in the message.
  • Only a few calls still work, so you can see why: GET /v1/auth/me, signing out, changing your password, and switching to another organization. project.suspended and organization.suspended are { at, reason } (null when not suspended).
  • The organization’s own pages in the console (members, projects) answer 403 organization_suspended, except reading it and leaving it.
Response (403)
{  "error": {    "code": "project_suspended",    "message": "this project's organization is suspended: <reason>. Contact support."  }}

Stop retrying when you get project_suspended: every call fails until the suspension is lifted. Contact support to resolve it.

try {  await client.sessions.create({ browser: true });} catch (err) {  if (err instanceof BoxlineError && err.code === "project_suspended") {    const { suspended } = (await client.me()).project;    console.error(`Suspended since ${suspended?.at}: ${suspended?.reason ?? "no reason given"}`);    process.exit(1); // do not retry  }  throw err;}

These docs describe a beta API. Endpoints, fields and SDK methods may change before general availability; breaking changes will be listed in the changelog.