99.99% Uptimeby Solari Status ↗

Solari

Last updated: 2026-10-28

Solari for Research Agents: Parallel Pages and Proxies

How do I run research agents on Solari?

Run a research agent on Solari: one browser session per page, a proxy country and IP tier per session, plan concurrency limits and session replays.

Solari runs a research agent's pages in parallel, one browser session per page: 8 ms session create on Steel's open-source benchmark, 150 concurrent browsers and 50 proxied sessions on Professional, at $0.07 per browser hour.

A research agent opens every page that might answer its question, and in production that list outgrows one browser fast. Some sources serve a different page, or a block page, depending on where the request comes from, and every citation needs a record of the page the agent actually read.

Solari covers all three on one account: a browser session per page, a proxy country and IP tier only where a source needs one, and a recording of each session the agent cites. Self-hosting Chromium means running the browser fleet, the proxy contract and the log store in-house; Solari replaces all three with one API (docs.getsolari.com).

Solari's Own Research Agents

Solari runs its own marketing system in a Solari sandbox, and part of it is a set of research agents.

Every week they open competitor blogs, pricing pages, changelogs and sitemaps in Solari browsers, read what changed and write it into notes that the system's writing agents draft from.

Another agent asks answer engines a fixed set of category questions and records which vendors each answer names. That becomes the table at the top of the weekly signals.

One detail from a recent run shows what the work is like. On two competitor sites, the blog URLs the agent guessed from link text returned 404s, and it found the real addresses only after reading each site's sitemap.xml.

Most of a research agent's time goes on this: lots of short, independent page reads, retried and redirected, with the reasoning in between. A long-running loop holds the plan, the notes and the code, and each page gets a short browser session that opens, reads and is released.

What Does a Research Agent Need From Its Infrastructure?

A research agent needs six things: fast session starts, enough sessions at once, a network location per session, a way through bot defences, logged-in access to some sources, and a record of what it read. Solari ships a feature for each.

Need

Why it matters for research

Solari feature

Docs

Fast, short sessions

One session per page multiplies setup time by the page count

Cloud Browsers

Sessions

Concurrency

The queue has to finish while the question still matters

Plan limits

Pricing

Location per session

Prices, search results and availability differ by country

Proxies

Proxies

Bot defences

Sources behind Cloudflare, DataDome, Akamai or PerimeterX

Stealth, captcha solving

Stealth

Logged-in sources

Paywalled databases, internal wikis, dashboards

Profiles

Profiles

A record of what was read

Citations that can be checked afterwards

Session recording

Recording

Session Start Time on Steel's Browserbench

Solari averaged 199.9 ms end to end, from create to release, across 5,000 runs on Steel's open-source benchmark, with the results in PR #4 (github.com/steel-dev/browserbench).

That number matters more for research agents than for most workloads. A research run opens one session per page, not one long session per task, so setup time is paid on every page and is the first thing to measure on any vendor.

How Many Pages Does Solari Run at Once?

Solari runs 150 concurrent browsers on the $200 Professional plan, and each plan carries a separate stealth cap for proxied sessions (docs.getsolari.com/pricing).

Plan

Price

Concurrent browsers

Concurrent stealth sessions

Starter

$20 / month

20

10

Professional

$200 / month

150

50

Team

custom

150+

75

Enterprise

custom

100,000

75

The stealth cap is counted in addition to the browser cap, and Enterprise's 100,000 concurrent browsers apply to standard sessions (docs.getsolari.com/pricing).

Proxies and captcha solving both run on stealth sessions, so the stealth column is the ceiling for proxied sessions. A stealth session over that cap gets an HTTP 429 while the main browser cap still has room (docs.getsolari.com/pricing).

In practice a research agent runs two pools. Public pages, search results and structured data go through default sessions, "fastest to start and to load pages", and only the sources that block or vary by location go through the stealth pool (docs.getsolari.com/stealth).

Proxies per Session

Solari sets a proxy on each session: pass proxy: { country } at create time and every session can exit from a different country, across 15 two-letter country codes (docs.getsolari.com/proxies).

Each session also takes one of three IP tiers. Residential, the default, gives "everyday home-internet IPs"; Static gives "one fixed IP that stays the same all session"; Mobile gives "cellular carrier IPs" for "the toughest targets that block residential IPs" (docs.getsolari.com/proxies).

Static ISP IPs run in 12 of the 15 countries (docs.getsolari.com/proxies).

Some flows span several sessions, such as a login followed by a search, or a paginated archive that challenges every new IP. Sessions created with the same proxy.session label get the same exit IP (docs.getsolari.com/proxies).

Each session response includes a proxy object with the country, the tier and a timezoneId that matches the IP's location. The agent checks that session.proxy is present before trusting the session (docs.getsolari.com/proxies).

Solari bills proxy traffic at $4.00 per GB on Professional, Team and Enterprise, and $6.00 per GB on Starter; proxies run on every paid plan (docs.getsolari.com/pricing).

Captcha solving is one more option on the same session, handling "reCaptcha v2/v3, hCaptcha, Turnstile, and others", and Solari bills it at $0.005 per solve on Professional (docs.getsolari.com/pricing).

The Code: A Queue of Sources, a Session per Page

This TypeScript sample uses the calls in the sessions guide and the proxies guide. It creates one session per source, adds stealth and a proxy only when the source needs them, checks that the proxy was applied, reads the page and releases the session. Two pools, each sized to a plan limit, keep proxied sessions under the stealth cap.

import { Solari } from "@solarisdk/browser"
import { chromium } from "playwright-core"

const client = new Solari({ apiKey: process.env.SOLARI_API_KEY! })

// Plan limits from the pricing page. These are Professional's.
const PLAN = { browsers: 150, stealth: 50 }

type Source = { url: string; country?: string } // country set = needs a proxy

async function read(source: Source) {
 const session = await client.sessions.create(
 source.country
 ? { stealth: true, proxy: { country: source.country } } // proxies run on stealth
: {} // default: fastest session
 )
 try {
 if (source.country && !session.proxy) throw new Error("session has no proxy")
 const browser = await chromium.connectOverCDP(session.cdpEndpoint)
 const page = await browser.newPage()
 await page.goto(source.url)
 const text = await page.locator("body").innerText()
 await browser.close()
 return { url: source.url, country: session.proxy?.country ?? null, text }
 } finally {
 await client.sessions.releaseAndWait(session.id)
 }
}

async function pool(sources: Source[], size: number) {
 const out: unknown[] = []
 let next = 0
 const worker = async () => {
 while (next < sources.length) {
 const s = sources[next++]
 out.push(await read(s).catch((e) => ({ url: s.url, error: String(e) })))
 }
 }
 await Promise.all(Array.from({ length: size }, worker))
 return out
}

export async function research(sources: Source[]) {
 const proxied = sources.filter((s) => s.country)
 const open = sources.filter((s) => !s.country)
 return [...(await pool(open, PLAN.browsers)),...(await pool(proxied, PLAN.stealth))]
}
import { Solari } from "@solarisdk/browser"
import { chromium } from "playwright-core"

const client = new Solari({ apiKey: process.env.SOLARI_API_KEY! })

// Plan limits from the pricing page. These are Professional's.
const PLAN = { browsers: 150, stealth: 50 }

type Source = { url: string; country?: string } // country set = needs a proxy

async function read(source: Source) {
 const session = await client.sessions.create(
 source.country
 ? { stealth: true, proxy: { country: source.country } } // proxies run on stealth
: {} // default: fastest session
 )
 try {
 if (source.country && !session.proxy) throw new Error("session has no proxy")
 const browser = await chromium.connectOverCDP(session.cdpEndpoint)
 const page = await browser.newPage()
 await page.goto(source.url)
 const text = await page.locator("body").innerText()
 await browser.close()
 return { url: source.url, country: session.proxy?.country ?? null, text }
 } finally {
 await client.sessions.releaseAndWait(session.id)
 }
}

async function pool(sources: Source[], size: number) {
 const out: unknown[] = []
 let next = 0
 const worker = async () => {
 while (next < sources.length) {
 const s = sources[next++]
 out.push(await read(s).catch((e) => ({ url: s.url, error: String(e) })))
 }
 }
 await Promise.all(Array.from({ length: size }, worker))
 return out
}

export async function research(sources: Source[]) {
 const proxied = sources.filter((s) => s.country)
 const open = sources.filter((s) => !s.country)
 return [...(await pool(open, PLAN.browsers)),...(await pool(proxied, PLAN.stealth))]
}
import { Solari } from "@solarisdk/browser"
import { chromium } from "playwright-core"

const client = new Solari({ apiKey: process.env.SOLARI_API_KEY! })

// Plan limits from the pricing page. These are Professional's.
const PLAN = { browsers: 150, stealth: 50 }

type Source = { url: string; country?: string } // country set = needs a proxy

async function read(source: Source) {
 const session = await client.sessions.create(
 source.country
 ? { stealth: true, proxy: { country: source.country } } // proxies run on stealth
: {} // default: fastest session
 )
 try {
 if (source.country && !session.proxy) throw new Error("session has no proxy")
 const browser = await chromium.connectOverCDP(session.cdpEndpoint)
 const page = await browser.newPage()
 await page.goto(source.url)
 const text = await page.locator("body").innerText()
 await browser.close()
 return { url: source.url, country: session.proxy?.country ?? null, text }
 } finally {
 await client.sessions.releaseAndWait(session.id)
 }
}

async function pool(sources: Source[], size: number) {
 const out: unknown[] = []
 let next = 0
 const worker = async () => {
 while (next < sources.length) {
 const s = sources[next++]
 out.push(await read(s).catch((e) => ({ url: s.url, error: String(e) })))
 }
 }
 await Promise.all(Array.from({ length: size }, worker))
 return out
}

export async function research(sources: Source[]) {
 const proxied = sources.filter((s) => s.country)
 const open = sources.filter((s) => !s.country)
 return [...(await pool(open, PLAN.browsers)),...(await pool(proxied, PLAN.stealth))]
}

To read the same page from two places, such as a pricing page seen from Britain and from Australia, queue it twice with country: "gb" and country: "au". For gb, timezoneId comes back as "Europe/London" (docs.getsolari.com/proxies).

For teams that prefer not to manage CDP, client.launch({ stealth: true, proxy: { country: "gb" } }) opens and connects in one call, and browser.close() cleans up (docs.getsolari.com/sessions).

Logged-In Sources and a Record of What Was Read

Solari profiles cover sources behind a login: a profile saves the login, cookies and site data, and a session created with profileId starts already signed in (docs.getsolari.com/profiles).

A profile seeds the session's default context. For a new context created in code, apply session.storageState to it so the login carries over (docs.getsolari.com/profiles).

Solari recording is how research citations get checked. Create the session with recording: true; afterwards getReplayUrl returns a temporary link and downloadReplay returns the run as NDJSON, "a line-by-line log of everything that happened on the page" (docs.getsolari.com/recording).

Solari keeps replays for 7 days on Starter, 30 on Professional and 90 on Team and Enterprise (docs.getsolari.com/pricing).

Recording captures input values by default, so leave it off on any session that types a password (docs.getsolari.com/recording).

Running the Loop in a Sandbox Next to the Browsers

A Solari sandbox is an isolated Linux machine for the loop that plans, parses and writes notes: create it with SandboxClient, run commands with commands.run and keep notes with files.write (docs.getsolari.com/sandboxes).

A sandbox pauses after the idle timeout set at creation, which keeps a weekly research loop from billing while it waits (docs.getsolari.com/sandboxes).

Browsers and sandboxes share one account, one bill and one slr_live_ key (docs.getsolari.com).

Solari and Its Peers for Research Agents

Solari is the full research-agent stack on one account: a browser session per page, a proxy only where a source needs one, a profile for each logged-in source, recording on the sessions the agent cites, and the loop in a sandbox.

Layer

Solari

Peers

Browser sessions

Cloud Browsers, Playwright or CDP

Browserbase, Steel, Kernel, Hyperbrowser, self-hosted Playwright

Proxies

Per session, three tiers, $4.00 per GB on Professional (pricing)

Browserbase lists 5 GB of proxies on its $99 Startup plan (browserbase.com/pricing); Bright Data for proxy networks

Bulk extraction

Agent-driven reads, one session per page

Apify, Bright Data

Code execution

Sandboxes, same account

E2B, Daytona, Modal

Solari bills $0.07 per browser hour on the Professional plan (docs.getsolari.com/pricing).

Browserbase lists $0.10 per browser hour in overage on its $99 Startup plan, against Solari's $0.07 on Professional (browserbase.com/pricing).

Browserbase lists 100 concurrent browsers on its $99 Startup plan, and Solari runs 150 on the $200 Professional plan (browserbase.com/pricing).

Solari's Team browser hour, $0.05, is the lowest list price in the browser-vendor comparison on the pricing page (www.getsolari.com/pricing).

Where Each Fits

Browserbase is the more established vendor with the larger ecosystem; Solari is the younger company and moves faster on speed and price. Apify and Bright Data fit bulk data extraction, and teams already on E2B, Daytona or Modal for sandboxes add Solari browsers next to them, while on Solari the browser and the sandbox share one account (getsolari.com/blog/introducing-solari).

Key Facts

FAQ

How Many Pages Can a Research Agent Read in Parallel on Solari?

Solari runs 150 concurrent browsers on Professional, with 50 of them as stealth sessions for proxied sources; Team and Enterprise raise the stealth cap to 75, and Enterprise runs 100,000 standard browsers (docs.getsolari.com/pricing).

Can Each Solari Browser Session Use a Different Proxy Country?

Yes. Each Solari session takes its own proxy: { country } and one of three IP tiers, residential, static or mobile, and sessions sharing a proxy.session label keep the same exit IP (docs.getsolari.com/proxies).

How Does a Research Agent Show What It Actually Read?

Solari records any session created with recording: true. getReplayUrl returns a replay link and downloadReplay returns an NDJSON log of everything that happened on the page (docs.getsolari.com/recording).

Sources

  1. https://github.com/steel-dev/browserbench

  2. https://docs.getsolari.com

  3. https://docs.getsolari.com/sessions

  4. https://docs.getsolari.com/pricing

  5. https://www.getsolari.com/pricing

  6. https://docs.getsolari.com/proxies

  7. https://docs.getsolari.com/stealth

  8. https://docs.getsolari.com/profiles

  9. https://docs.getsolari.com/recording

  10. https://docs.getsolari.com/sandboxes

  11. https://www.browserbase.com/pricing

  12. https://getsolari.com/blog/introducing-solari

CTA: Send a first proxied session to a source that varies by country with the Solari proxies guide, start on Solari's free plan, or book a call at getsolari.com to size both pools for a production research agent.