浏览器、profile 与登录态
本文说明当前工程「用哪个浏览器、用哪份 profile、登录态存在哪」,以及换浏览器带来的实际后果。前文 04 讲的是请求与响应的形状,本文讲的是浏览器本身。
一、一个浏览器,多个任务
浏览器是全进程共享的:一个浏览器进程、一份 profile,任务之间靠页签隔离。
| 行为 | 说明 |
|---|---|
第一次 start | 把浏览器拉起来 |
之后每次 start | 配置兼容时复用浏览器,新开任务页签 |
还有其他任务时 close | 只关掉该任务自己的页签 |
最后一个任务 close | 保留浏览器与数据页,移除旧任务监听及路由 |
close --close-browser | 显式关闭闲置浏览器;有其他任务时拒绝 |
shutdown | 关掉全部任务与共享浏览器,服务进程不退出 |
为什么不能一个任务一个浏览器。 用户数据目录天生是单例:同一个 User Data 目录同时只允许一个浏览器进程,第二个进程会把命令行交给已有实例然后自己退出。所以「共用一份 profile、登录态只养一次」和「一个任务一个浏览器」只能二选一 —— 这里选了前者。
代价是上下文级设置是所有任务共享的(Cookie、地理位置、离线、额外请求头、权限),因为它们本来就挂在同一个浏览器上下文上;get_browser_state 只列任务自己的页签,switch_tab 的索引也只在任务自己的页签里数。
二、start 的 browser 参数
{"method":"start","params":{"browser":"edge","headless":false}}| 取值 | 浏览器 | 引擎 | 启动方式 | profile | 什么时候用 |
|---|---|---|---|---|---|
不传 / auto | 本机 Google Chrome,没装且未显式选 profile 时退回内置 Chromium | Chromium | 落到 Chrome 时走 CDP,退回内置 Chromium 时走持久化上下文 | 见第三节 | 默认(推荐) |
chrome | 只用本机 Google Chrome | Chromium | CDP(自己拉进程 + 远程调试端口) | 默认一份 shared-default;可显式选择命名 profile 或独立目录,见 39 | 需要 Google 登录之类的站点,或要确认「本机 Chrome 下的表现」 |
chromium | 只用内置的那份(发行包内嵌),完全不碰本机 Chrome | Chromium | 持久化上下文 | 托管 profile(按端口派生) | 怀疑本机 Chrome 的扩展或登录态干扰时做对照 |
edge | 只用本机 Microsoft Edge | Chromium | CDP | Edge 专用托管 profile | 站点在 Chrome 下用不了,或要对照两个浏览器的差异 |
firefox | Playwright 自带的那份 Firefox | Firefox | 持久化上下文 | 托管 profile(按端口派生) | 站点在 Chromium 下用不了,见第五节 |
「启动方式」这一列是实现细节,但对结果有影响:默认 CDP 路径使用独立托管 profile,因此通常不要求先关掉使用其它目录的 Chrome;显式选目录或克隆时必须检查目录占用;代价是创建期的某些设置要另想办法补,见 27。
别名也认(msedge / google-chrome / bundled / ff 等);写了不认识的值会直接失败并列出可选值。
auto 与显式取值的区别是「能不能悄悄换一个」:没有显式选择 profile 且不传 browser 时服务按老规矩退让(本机没有 Chrome 就用内置 Chromium),并把原因写进 data.browser.note;显式写了 chrome / edge 就是「我就要这个」,没装会直接报错并说清怎么改 —— 否则「明明要了 Edge,结果用 Chrome 跑出另一种页面」这类问题很难查。
一次只能有一个浏览器。 类型与 profile 都必须在结束任务并显式关闭保留的浏览器后才能切换(只 close 自己的任务;其他任务由所属用户结束),不能在任务运行中强行切换:那会连累别的任务的页签,服务会明确报错。想同时用两个浏览器(例如一边 Chrome 一边 Edge),再起一个服务进程,给它们配不同的端口与 profile 目录。
回执里的「我要的」与「实际用的」
{"data":{"id":"1001","requestedBrowser":"firefox","effectiveBrowser":"firefox","engineHonored":true,
"browser":{"type":"firefox","engine":"firefox","mode":"managed","headless":false,
"profileDir":"~/.config/browseruse/profiles/shared-10049"}}}| 字段 | 含义 |
|---|---|
requestedBrowser | 这次请求里写的那个值 |
effectiveBrowser | 实际落到的那个(auto 不会出现在这里) |
engineHonored | 服务实例有没有按 browser 参数切浏览器 |
mode | managed(持久化上下文)或 cdp(自己拉进程 + 远程调试端口) |
cdp | 只在 mode=cdp 时出现:product(浏览器亲口报的版本)、protocolVersion,以及 notes(用协议补了哪些创建期设置,补失败的也在这里)。见 27 |
profileDir | 这次真正用的 profile 目录 |
profileSeenBefore | 这份 profile 在这次启动之前就已经有内容了吗 |
note | 这次启动方式与 profile 的说明:走 CDP 时说明用的是哪条路与哪份 profile;用户 profile 用不上时,这里是退回托管 profile 的原因 |
profileNote | 对「这份 profile 里有没有登录态」的说明,例如「之前用过(上次是 browser=chrome),里面已有的登录态应该还在」 |
previousEngine / previousBrowser | 上次用这份 profile 的引擎与浏览器类型 |
engineHonored:false 表示这个服务实例没有按 browser 参数切浏览器(老版本发行包只认 headless,会静默忽略 browser,回执照样 ok:true),此时 data.engineWarning 会说明原因。要不要用 get_config 看服务端认的 engine / configuredType 也行。
profileSeenBefore 回答的是「要不要重新登录」:它只说明这份 profile 里有内容,不保证某个具体站点的登录态仍然有效。
三、profile 目录
直接启动 Java 时,默认托管 profile 位于 ~/.config/browseruse/profiles/ 下;命名根目录可通过 browser.profiles.dir 配置,显式目录可以在其它位置。本机 Chrome 与其它浏览器用的不是同一份。
3.1 CLI 启动的服务
dsb server start 按服务端口指定持久化目录:默认端口 10049 保留 .dsb-backend/profile,其他端口使用 .dsb-backend/profile-<port>。同一端口重启后仍用原目录;不同端口默认不争用同一份 profile。
3.2 直接启动 Java 服务
| 浏览器 | 默认端口 10049 | 其他端口 | 显式路径配置 |
|---|---|---|---|
| Chrome CDP | shared-default | shared-<port> | browser.chrome.cdpProfileDir 优先于 browser.profileDir |
| Edge | edge | edge-<port> | browser.edge.profileDir |
| 内置 Chromium / Firefox | shared-10049 | shared-<port> | browser.profileDir;browser.profileDir.perPort=false 可恢复 shared |
表内默认目录位于 ~/.config/browseruse/profiles/ 下。显式目录优先;若多个服务被显式配置为同一目录,仍会发生占用冲突。登录态跟着目录走,不自动迁移。
同一服务的后续兼容任务复用浏览器并新开页签,不接管保留的数据页及用户打开的页面。配置不兼容时返回错误,即使没有活动任务也不会自动关闭浏览器。确认需要切换后使用 close --close-browser,再启动新任务。
用 get_config 与启动回执中的实际 profileDir 核验目录。选择了命名 profile 时以本次启动回执为准。Firefox 与 Chromium 的目录格式不通用,Edge 也不应与 Chrome 共用 profile。
四、显式选择与独立克隆
推荐先用 dsb profiles 查看服务端发现的目录,再用 dsb profile clone 离线复制需要的子 profile,最后通过命名 profile 启动:
dsb profile clone --name litongjava --source-user-data-dir "<Chrome User Data>" --source-profile-directory Default
dsb --id 1001 start --browser chrome --headful --profile litongjava完整字段、目录选择与安全边界见 39:profile 列表、克隆与选择。显式选择只支持 Chrome;此时省略 browser 或传 auto 也按 Chrome 处理,不会改用其它浏览器。未知名称、目录错误或启动失败都直接报错,不会回退到默认 profile;命名选择不能与显式目录混用。
browser.chrome.useUserProfile=true 是旧的配置入口,尝试直接使用用户自己的 User Data,仍然通过 CDP 连接。Chrome 对系统默认用户数据目录的远程调试限制与 RemoteDebuggingAllowed 策略不是同一件事:把该策略设为允许并不能解除默认目录限制,不应以修改注册表或降级浏览器作为本功能的前提。
支持的做法是使用非默认目录的独立副本。复制 profile 并非一概不可行,但加密 Cookie、已保存密码与网站会话可能无法沿用,需要人工重新登录;不保证保留 Google 或任何网站的登录状态。
仅未显式选 profile 的旧配置路径仍受 browser.chrome.profileFallback 控制:失败时可以退回托管目录,并在 data.browser.note 说明原因。它不覆盖显式选择的“失败不回退”规则。
这条路用之前先知道两件事:
| 事项 | 说明 |
|---|---|
set_credentials 用不了 | HTTP 基本认证的凭据只能在创建上下文时设置,而 CDP 这条路的上下文不由服务创建。需要它时改用 browser=chromium 或 browser=firefox,失败信息里会直接给出这两个取值 |
| 页面触发的下载 | 服务已经在启动时用协议命令把下载目录设成约定目录(见 27 第五节),不设的话会落到浏览器自己的下载目录。pdf 命令不受影响(路径由服务自己算) |
本机 Chrome 这条路的页面视口一直跟着窗口走,不套视口模拟,所以 browser.viewport 对它没有影响(见 06)。
五、换成 Firefox
browser.engine=firefox 或 browser=firefox 时改走 Playwright 自带的 Firefox,配同一份托管 profile。
| 差异 | 说明 |
|---|---|
pdf 命令 | 只有 Chromium 支持,Firefox 下返回明确的中文失败原因 |
| 用户自己的 Chrome profile | browser.chrome.useUserProfile 对 Firefox 无效(那条路要 CDP,Firefox 没有) |
| 启动参数 | 没有 --no-sandbox / chromiumSandbox / --profile-directory,Firefox 下不传 |
| 本机装的 Firefox | 用不上:Playwright 的 Firefox 是打过补丁的构建(juggler 协议),不要配 browser.firefox.path 指到本机那份 |
| UA | 不覆写成 Chrome,UA 就是 Firefox 自己的 |
为什么要这个开关:有的站点在 Chromium 下用不了。中国商标网统一身份认证(sso.cnipa.gov.cn)的 SPA 会做开发者工具检测,Chromium 会走到空白页或 HTTP 400,同一流程在 Firefox 下能正常渲染出登录表单。
start 的返回里会多一个 data.browser.engine,用它确认这次到底跑的是哪个引擎。换引擎等于换一套 profile 格式,所以要重新登录一次。
六、关于 Chromium 沙箱
默认策略:Windows / macOS 这类普通桌面环境开启,Linux 关闭(服务多数跑在容器里、以 root 运行,而 Chrome 以 root 启动会直接报错退出)。
| 平台 / 浏览器 | 默认 | 原因 |
|---|---|---|
Windows / macOS 上的 chrome、chromium、auto | 开启 | 普通桌面环境沙箱可用;关掉换不来任何东西,只换来更差的隔离 |
Windows / macOS 上的 edge | 开启 | Edge 走 CDP(端口)那条路,沙箱不影响启动 |
| Linux 上的任何浏览器 | 关闭 | 以 root 运行时必须传 --no-sandbox |
browser.chromium.sandbox 三档取值:true 始终开启 / false 始终关闭 / 不配按平台默认。两条启动路径(Playwright 的持久化上下文与 CDP 那条自己拉进程的路)看同一个开关,不会一半开一半关。
两点容易误解的地方:
--no-sandbox是 Playwright 自己加的,不是本服务传的:Playwright 的chromiumSandbox默认就是关的,只要不显式开启沙箱,这条标志就一直在。- Edge 的问题是「沙箱 + 管道」这个组合:实测开沙箱时,Playwright 的
--remote-debugging-pipe会让 Edge 启动即退出(Target page, context or browser has been closed),换成--remote-debugging-port就一切正常。所以解决办法是换启动方式,而不是关沙箱。
不要为了「藏掉自动化特征」去加 --disable-blink-features=AutomationControlled:那个参数会触发浏览器顶部的「不受支持的命令行标志」提示。需要补充启动参数用 browser.chrome.extraArgs / browser.edge.extraArgs / browser.firefox.extraArgs,改完要重启服务并重新创建浏览器实例,旧窗口不会自动应用新参数。
调试端口不要用 9222。 它不是浏览器的内置默认值,只是各类工具约定俗成的端口,跟着用会互相抢。CDP 那条路默认让浏览器自己挑空闲端口(一定在 10000 以上),需要固定端点时用 browser.chrome.debugPort 钉一个 10000 以上的值,原因与排障见 27 第八节。
