browser-use 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +761 -0
  3. package/dist/agent/cloud-events.d.ts +264 -0
  4. package/dist/agent/cloud-events.js +318 -0
  5. package/dist/agent/gif.d.ts +15 -0
  6. package/dist/agent/gif.js +215 -0
  7. package/dist/agent/index.d.ts +8 -0
  8. package/dist/agent/index.js +8 -0
  9. package/dist/agent/message-manager/service.d.ts +30 -0
  10. package/dist/agent/message-manager/service.js +208 -0
  11. package/dist/agent/message-manager/utils.d.ts +2 -0
  12. package/dist/agent/message-manager/utils.js +41 -0
  13. package/dist/agent/message-manager/views.d.ts +26 -0
  14. package/dist/agent/message-manager/views.js +73 -0
  15. package/dist/agent/prompts.d.ts +52 -0
  16. package/dist/agent/prompts.js +259 -0
  17. package/dist/agent/service.d.ts +290 -0
  18. package/dist/agent/service.js +2200 -0
  19. package/dist/agent/views.d.ts +741 -0
  20. package/dist/agent/views.js +537 -0
  21. package/dist/browser/browser.d.ts +7 -0
  22. package/dist/browser/browser.js +5 -0
  23. package/dist/browser/context.d.ts +8 -0
  24. package/dist/browser/context.js +4 -0
  25. package/dist/browser/dvd-screensaver.d.ts +101 -0
  26. package/dist/browser/dvd-screensaver.js +270 -0
  27. package/dist/browser/extensions.d.ts +63 -0
  28. package/dist/browser/extensions.js +359 -0
  29. package/dist/browser/index.d.ts +10 -0
  30. package/dist/browser/index.js +9 -0
  31. package/dist/browser/playwright-manager.d.ts +47 -0
  32. package/dist/browser/playwright-manager.js +146 -0
  33. package/dist/browser/profile.d.ts +196 -0
  34. package/dist/browser/profile.js +815 -0
  35. package/dist/browser/session.d.ts +505 -0
  36. package/dist/browser/session.js +3409 -0
  37. package/dist/browser/types.d.ts +1184 -0
  38. package/dist/browser/types.js +1 -0
  39. package/dist/browser/utils.d.ts +1 -0
  40. package/dist/browser/utils.js +19 -0
  41. package/dist/browser/views.d.ts +78 -0
  42. package/dist/browser/views.js +72 -0
  43. package/dist/cli.d.ts +2 -0
  44. package/dist/cli.js +44 -0
  45. package/dist/config.d.ts +108 -0
  46. package/dist/config.js +430 -0
  47. package/dist/controller/index.d.ts +3 -0
  48. package/dist/controller/index.js +3 -0
  49. package/dist/controller/registry/index.d.ts +2 -0
  50. package/dist/controller/registry/index.js +2 -0
  51. package/dist/controller/registry/service.d.ts +45 -0
  52. package/dist/controller/registry/service.js +184 -0
  53. package/dist/controller/registry/views.d.ts +55 -0
  54. package/dist/controller/registry/views.js +174 -0
  55. package/dist/controller/service.d.ts +49 -0
  56. package/dist/controller/service.js +1176 -0
  57. package/dist/controller/views.d.ts +241 -0
  58. package/dist/controller/views.js +88 -0
  59. package/dist/dom/clickable-element-processor/service.d.ts +11 -0
  60. package/dist/dom/clickable-element-processor/service.js +60 -0
  61. package/dist/dom/dom_tree/index.js +1400 -0
  62. package/dist/dom/history-tree-processor/service.d.ts +14 -0
  63. package/dist/dom/history-tree-processor/service.js +75 -0
  64. package/dist/dom/history-tree-processor/view.d.ts +54 -0
  65. package/dist/dom/history-tree-processor/view.js +56 -0
  66. package/dist/dom/playground/extraction.d.ts +19 -0
  67. package/dist/dom/playground/extraction.js +187 -0
  68. package/dist/dom/playground/process-dom.d.ts +1 -0
  69. package/dist/dom/playground/process-dom.js +5 -0
  70. package/dist/dom/playground/test-accessibility.d.ts +44 -0
  71. package/dist/dom/playground/test-accessibility.js +111 -0
  72. package/dist/dom/service.d.ts +19 -0
  73. package/dist/dom/service.js +227 -0
  74. package/dist/dom/utils.d.ts +1 -0
  75. package/dist/dom/utils.js +6 -0
  76. package/dist/dom/views.d.ts +61 -0
  77. package/dist/dom/views.js +247 -0
  78. package/dist/event-bus.d.ts +11 -0
  79. package/dist/event-bus.js +19 -0
  80. package/dist/exceptions.d.ts +10 -0
  81. package/dist/exceptions.js +22 -0
  82. package/dist/filesystem/file-system.d.ts +68 -0
  83. package/dist/filesystem/file-system.js +412 -0
  84. package/dist/filesystem/index.d.ts +1 -0
  85. package/dist/filesystem/index.js +1 -0
  86. package/dist/index.d.ts +31 -0
  87. package/dist/index.js +33 -0
  88. package/dist/integrations/gmail/actions.d.ts +12 -0
  89. package/dist/integrations/gmail/actions.js +113 -0
  90. package/dist/integrations/gmail/index.d.ts +2 -0
  91. package/dist/integrations/gmail/index.js +2 -0
  92. package/dist/integrations/gmail/service.d.ts +61 -0
  93. package/dist/integrations/gmail/service.js +260 -0
  94. package/dist/llm/anthropic/chat.d.ts +28 -0
  95. package/dist/llm/anthropic/chat.js +126 -0
  96. package/dist/llm/anthropic/index.d.ts +2 -0
  97. package/dist/llm/anthropic/index.js +2 -0
  98. package/dist/llm/anthropic/serializer.d.ts +68 -0
  99. package/dist/llm/anthropic/serializer.js +285 -0
  100. package/dist/llm/aws/chat-anthropic.d.ts +61 -0
  101. package/dist/llm/aws/chat-anthropic.js +176 -0
  102. package/dist/llm/aws/chat-bedrock.d.ts +15 -0
  103. package/dist/llm/aws/chat-bedrock.js +80 -0
  104. package/dist/llm/aws/index.d.ts +3 -0
  105. package/dist/llm/aws/index.js +3 -0
  106. package/dist/llm/aws/serializer.d.ts +5 -0
  107. package/dist/llm/aws/serializer.js +68 -0
  108. package/dist/llm/azure/chat.d.ts +15 -0
  109. package/dist/llm/azure/chat.js +83 -0
  110. package/dist/llm/azure/index.d.ts +1 -0
  111. package/dist/llm/azure/index.js +1 -0
  112. package/dist/llm/base.d.ts +16 -0
  113. package/dist/llm/base.js +1 -0
  114. package/dist/llm/deepseek/chat.d.ts +15 -0
  115. package/dist/llm/deepseek/chat.js +51 -0
  116. package/dist/llm/deepseek/index.d.ts +2 -0
  117. package/dist/llm/deepseek/index.js +2 -0
  118. package/dist/llm/deepseek/serializer.d.ts +6 -0
  119. package/dist/llm/deepseek/serializer.js +57 -0
  120. package/dist/llm/exceptions.d.ts +10 -0
  121. package/dist/llm/exceptions.js +18 -0
  122. package/dist/llm/google/chat.d.ts +20 -0
  123. package/dist/llm/google/chat.js +144 -0
  124. package/dist/llm/google/index.d.ts +2 -0
  125. package/dist/llm/google/index.js +2 -0
  126. package/dist/llm/google/serializer.d.ts +6 -0
  127. package/dist/llm/google/serializer.js +64 -0
  128. package/dist/llm/groq/chat.d.ts +15 -0
  129. package/dist/llm/groq/chat.js +52 -0
  130. package/dist/llm/groq/index.d.ts +3 -0
  131. package/dist/llm/groq/index.js +3 -0
  132. package/dist/llm/groq/parser.d.ts +32 -0
  133. package/dist/llm/groq/parser.js +189 -0
  134. package/dist/llm/groq/serializer.d.ts +6 -0
  135. package/dist/llm/groq/serializer.js +56 -0
  136. package/dist/llm/messages.d.ts +77 -0
  137. package/dist/llm/messages.js +157 -0
  138. package/dist/llm/ollama/chat.d.ts +15 -0
  139. package/dist/llm/ollama/chat.js +77 -0
  140. package/dist/llm/ollama/index.d.ts +2 -0
  141. package/dist/llm/ollama/index.js +2 -0
  142. package/dist/llm/ollama/serializer.d.ts +6 -0
  143. package/dist/llm/ollama/serializer.js +53 -0
  144. package/dist/llm/openai/chat.d.ts +38 -0
  145. package/dist/llm/openai/chat.js +174 -0
  146. package/dist/llm/openai/index.d.ts +3 -0
  147. package/dist/llm/openai/index.js +3 -0
  148. package/dist/llm/openai/like.d.ts +17 -0
  149. package/dist/llm/openai/like.js +19 -0
  150. package/dist/llm/openai/serializer.d.ts +6 -0
  151. package/dist/llm/openai/serializer.js +57 -0
  152. package/dist/llm/openrouter/chat.d.ts +15 -0
  153. package/dist/llm/openrouter/chat.js +74 -0
  154. package/dist/llm/openrouter/index.d.ts +2 -0
  155. package/dist/llm/openrouter/index.js +2 -0
  156. package/dist/llm/openrouter/serializer.d.ts +3 -0
  157. package/dist/llm/openrouter/serializer.js +3 -0
  158. package/dist/llm/schema.d.ts +6 -0
  159. package/dist/llm/schema.js +77 -0
  160. package/dist/llm/views.d.ts +15 -0
  161. package/dist/llm/views.js +12 -0
  162. package/dist/logging-config.d.ts +25 -0
  163. package/dist/logging-config.js +89 -0
  164. package/dist/mcp/client.d.ts +142 -0
  165. package/dist/mcp/client.js +638 -0
  166. package/dist/mcp/controller.d.ts +6 -0
  167. package/dist/mcp/controller.js +38 -0
  168. package/dist/mcp/index.d.ts +3 -0
  169. package/dist/mcp/index.js +3 -0
  170. package/dist/mcp/server.d.ts +134 -0
  171. package/dist/mcp/server.js +759 -0
  172. package/dist/observability-decorators.d.ts +158 -0
  173. package/dist/observability-decorators.js +286 -0
  174. package/dist/observability.d.ts +23 -0
  175. package/dist/observability.js +58 -0
  176. package/dist/screenshots/index.d.ts +1 -0
  177. package/dist/screenshots/index.js +1 -0
  178. package/dist/screenshots/service.d.ts +6 -0
  179. package/dist/screenshots/service.js +28 -0
  180. package/dist/sync/auth.d.ts +27 -0
  181. package/dist/sync/auth.js +205 -0
  182. package/dist/sync/index.d.ts +2 -0
  183. package/dist/sync/index.js +2 -0
  184. package/dist/sync/service.d.ts +21 -0
  185. package/dist/sync/service.js +146 -0
  186. package/dist/telemetry/index.d.ts +2 -0
  187. package/dist/telemetry/index.js +2 -0
  188. package/dist/telemetry/service.d.ts +12 -0
  189. package/dist/telemetry/service.js +85 -0
  190. package/dist/telemetry/views.d.ts +112 -0
  191. package/dist/telemetry/views.js +112 -0
  192. package/dist/tokens/index.d.ts +2 -0
  193. package/dist/tokens/index.js +2 -0
  194. package/dist/tokens/service.d.ts +35 -0
  195. package/dist/tokens/service.js +423 -0
  196. package/dist/tokens/views.d.ts +58 -0
  197. package/dist/tokens/views.js +1 -0
  198. package/dist/utils.d.ts +128 -0
  199. package/dist/utils.js +529 -0
  200. package/package.json +94 -5
@@ -0,0 +1,815 @@
1
+ import fs from 'node:fs';
2
+ import { promises as fsp } from 'node:fs';
3
+ import path from 'node:path';
4
+ import https from 'node:https';
5
+ import AdmZip from 'adm-zip';
6
+ import { CONFIG } from '../config.js';
7
+ import { observe_debug } from '../observability.js';
8
+ import { createLogger } from '../logging-config.js';
9
+ import { log_pretty_path, uuid7str } from '../utils.js';
10
+ const logger = createLogger('browser_use.browser.profile');
11
+ export const CHROME_DEBUG_PORT = 9242;
12
+ export const CHROME_DISABLED_COMPONENTS = [
13
+ 'AcceptCHFrame',
14
+ 'AutoExpandDetailsElement',
15
+ 'AvoidUnnecessaryBeforeUnloadCheckSync',
16
+ 'CertificateTransparencyComponentUpdater',
17
+ 'DestroyProfileOnBrowserClose',
18
+ 'DialMediaRouteProvider',
19
+ 'ExtensionManifestV2Disabled',
20
+ 'GlobalMediaControls',
21
+ 'HttpsUpgrades',
22
+ 'ImprovedCookieControls',
23
+ 'LazyFrameLoading',
24
+ 'LensOverlay',
25
+ 'MediaRouter',
26
+ 'PaintHolding',
27
+ 'ThirdPartyStoragePartitioning',
28
+ 'Translate',
29
+ 'AutomationControlled',
30
+ 'BackForwardCache',
31
+ 'OptimizationHints',
32
+ 'ProcessPerSiteUpToMainFrameThreshold',
33
+ 'InterestFeedContentSuggestions',
34
+ 'CalculateNativeWinOcclusion',
35
+ 'HeavyAdPrivacyMitigations',
36
+ 'PrivacySandboxSettings4',
37
+ 'AutofillServerCommunication',
38
+ 'CrashReporting',
39
+ 'OverscrollHistoryNavigation',
40
+ 'InfiniteSessionRestore',
41
+ 'ExtensionDisableUnsupportedDeveloper',
42
+ ];
43
+ export const CHROME_HEADLESS_ARGS = ['--headless=new'];
44
+ export const CHROME_DOCKER_ARGS = [
45
+ '--no-sandbox',
46
+ '--disable-gpu-sandbox',
47
+ '--disable-setuid-sandbox',
48
+ '--disable-dev-shm-usage',
49
+ '--no-xshm',
50
+ '--no-zygote',
51
+ '--disable-site-isolation-trials',
52
+ ];
53
+ export const CHROME_DISABLE_SECURITY_ARGS = [
54
+ '--disable-site-isolation-trials',
55
+ '--disable-web-security',
56
+ '--disable-features=IsolateOrigins,site-per-process',
57
+ '--allow-running-insecure-content',
58
+ '--ignore-certificate-errors',
59
+ '--ignore-ssl-errors',
60
+ '--ignore-certificate-errors-spki-list',
61
+ ];
62
+ export const CHROME_DETERMINISTIC_RENDERING_ARGS = [
63
+ '--deterministic-mode',
64
+ '--js-flags=--random-seed=1157259159',
65
+ '--force-device-scale-factor=2',
66
+ '--enable-webgl',
67
+ '--font-render-hinting=none',
68
+ '--force-color-profile=srgb',
69
+ ];
70
+ export const CHROME_DEFAULT_ARGS = [
71
+ '--disable-field-trial-config',
72
+ '--disable-background-networking',
73
+ '--disable-background-timer-throttling',
74
+ '--disable-backgrounding-occluded-windows',
75
+ '--disable-back-forward-cache',
76
+ '--disable-breakpad',
77
+ '--disable-client-side-phishing-detection',
78
+ '--disable-component-extensions-with-background-pages',
79
+ '--disable-component-update',
80
+ '--no-default-browser-check',
81
+ '--disable-dev-shm-usage',
82
+ '--disable-hang-monitor',
83
+ '--disable-ipc-flooding-protection',
84
+ '--disable-popup-blocking',
85
+ '--disable-prompt-on-repost',
86
+ '--disable-renderer-backgrounding',
87
+ '--metrics-recording-only',
88
+ '--no-first-run',
89
+ '--password-store=basic',
90
+ '--use-mock-keychain',
91
+ '--no-service-autorun',
92
+ '--export-tagged-pdf',
93
+ '--disable-search-engine-choice-screen',
94
+ '--unsafely-disable-devtools-self-xss-warnings',
95
+ '--enable-features=NetworkService,NetworkServiceInProcess',
96
+ '--enable-network-information-downlink-max',
97
+ '--test-type=gpu',
98
+ '--disable-sync',
99
+ '--allow-legacy-extension-manifests',
100
+ '--allow-pre-commit-input',
101
+ '--disable-blink-features=AutomationControlled',
102
+ '--install-autogenerated-theme=0,0,0',
103
+ '--log-level=2',
104
+ '--disable-focus-on-load',
105
+ '--disable-window-activation',
106
+ '--generate-pdf-document-outline',
107
+ '--no-pings',
108
+ '--ash-no-nudges',
109
+ '--disable-infobars',
110
+ '--simulate-outdated-no-au="Tue, 31 Dec 2099 23:59:59 GMT"',
111
+ '--hide-crash-restore-bubble',
112
+ '--suppress-message-center-popups',
113
+ '--disable-domain-reliability',
114
+ '--disable-datasaver-prompt',
115
+ '--disable-speech-synthesis-api',
116
+ '--disable-speech-api',
117
+ '--disable-print-preview',
118
+ '--safebrowsing-disable-auto-update',
119
+ '--disable-external-intent-requests',
120
+ '--disable-desktop-notifications',
121
+ '--noerrdialogs',
122
+ '--silent-debugger-extension-api',
123
+ '--disable-extensions-http-throttling',
124
+ '--extensions-on-chrome-urls',
125
+ '--disable-default-apps',
126
+ `--disable-features=${CHROME_DISABLED_COMPONENTS.join(',')}`,
127
+ ];
128
+ const DEFAULT_EXTENSIONS = [
129
+ {
130
+ name: 'uBlock Origin',
131
+ id: 'cjpalhdlnbpafiamejdnhcphjbkeiagm',
132
+ url: 'https://clients2.google.com/service/update2/crx?response=redirect&prodversion=130&acceptformat=crx3&x=id%3Dcjpalhdlnbpafiamejdnhcphjbkeiagm%26uc',
133
+ },
134
+ {
135
+ name: "I still don't care about cookies",
136
+ id: 'edibdbjcniadpccecjdfdjjppcpchdlm',
137
+ url: 'https://clients2.google.com/service/update2/crx?response=redirect&prodversion=130&acceptformat=crx3&x=id%3Dedibdbjcniadpccecjdfdjjppcpchdlm%26uc',
138
+ },
139
+ {
140
+ name: 'ClearURLs',
141
+ id: 'lckanjgmijmafbedllaakclkaicjfmnk',
142
+ url: 'https://clients2.google.com/service/update2/crx?response=redirect&prodversion=130&acceptformat=crx3&x=id%3Dlckanjgmijmafbedllaakclkaicjfmnk%26uc',
143
+ },
144
+ ];
145
+ const parseDisplayEnv = () => {
146
+ const width = process.env.BROWSER_USE_SCREEN_WIDTH;
147
+ const height = process.env.BROWSER_USE_SCREEN_HEIGHT;
148
+ if (width && height) {
149
+ const parsedWidth = Number(width);
150
+ const parsedHeight = Number(height);
151
+ if (!Number.isNaN(parsedWidth) && !Number.isNaN(parsedHeight)) {
152
+ return { width: parsedWidth, height: parsedHeight };
153
+ }
154
+ }
155
+ return null;
156
+ };
157
+ export const get_display_size = () => {
158
+ // Node.js lacks a portable cross-platform API for monitor size detection.
159
+ // Support manual overrides via env vars and fall back to null otherwise.
160
+ return parseDisplayEnv();
161
+ };
162
+ export const get_window_adjustments = () => {
163
+ if (process.platform === 'darwin') {
164
+ return [-4, 24];
165
+ }
166
+ if (process.platform === 'win32') {
167
+ return [-8, 0];
168
+ }
169
+ return [0, 0];
170
+ };
171
+ const validate_url = (url, schemes = []) => {
172
+ try {
173
+ const parsed = new URL(url);
174
+ if (schemes.length > 0 && parsed.protocol) {
175
+ const lowered = parsed.protocol.replace(':', '').toLowerCase();
176
+ if (!schemes.map((s) => s.toLowerCase()).includes(lowered)) {
177
+ throw new Error();
178
+ }
179
+ }
180
+ return url;
181
+ }
182
+ catch {
183
+ throw new Error(`Invalid URL format: ${url}`);
184
+ }
185
+ };
186
+ const validate_float_range = (value, min, max) => {
187
+ if (value < min || value > max) {
188
+ throw new Error(`Value ${value} outside of range ${min}-${max}`);
189
+ }
190
+ return value;
191
+ };
192
+ const validate_cli_arg = (arg) => {
193
+ if (!arg.startsWith('--')) {
194
+ throw new Error(`Invalid CLI argument: ${arg} (should start with --)`);
195
+ }
196
+ return arg;
197
+ };
198
+ export var ColorScheme;
199
+ (function (ColorScheme) {
200
+ ColorScheme["LIGHT"] = "light";
201
+ ColorScheme["DARK"] = "dark";
202
+ ColorScheme["NO_PREFERENCE"] = "no-preference";
203
+ ColorScheme["NULL"] = "null";
204
+ })(ColorScheme || (ColorScheme = {}));
205
+ export var Contrast;
206
+ (function (Contrast) {
207
+ Contrast["NO_PREFERENCE"] = "no-preference";
208
+ Contrast["MORE"] = "more";
209
+ Contrast["NULL"] = "null";
210
+ })(Contrast || (Contrast = {}));
211
+ export var ReducedMotion;
212
+ (function (ReducedMotion) {
213
+ ReducedMotion["REDUCE"] = "reduce";
214
+ ReducedMotion["NO_PREFERENCE"] = "no-preference";
215
+ ReducedMotion["NULL"] = "null";
216
+ })(ReducedMotion || (ReducedMotion = {}));
217
+ export var ForcedColors;
218
+ (function (ForcedColors) {
219
+ ForcedColors["ACTIVE"] = "active";
220
+ ForcedColors["NONE"] = "none";
221
+ ForcedColors["NULL"] = "null";
222
+ })(ForcedColors || (ForcedColors = {}));
223
+ export var ServiceWorkers;
224
+ (function (ServiceWorkers) {
225
+ ServiceWorkers["ALLOW"] = "allow";
226
+ ServiceWorkers["BLOCK"] = "block";
227
+ })(ServiceWorkers || (ServiceWorkers = {}));
228
+ export var RecordHarContent;
229
+ (function (RecordHarContent) {
230
+ RecordHarContent["OMIT"] = "omit";
231
+ RecordHarContent["EMBED"] = "embed";
232
+ RecordHarContent["ATTACH"] = "attach";
233
+ })(RecordHarContent || (RecordHarContent = {}));
234
+ export var RecordHarMode;
235
+ (function (RecordHarMode) {
236
+ RecordHarMode["FULL"] = "full";
237
+ RecordHarMode["MINIMAL"] = "minimal";
238
+ })(RecordHarMode || (RecordHarMode = {}));
239
+ export var BrowserChannel;
240
+ (function (BrowserChannel) {
241
+ BrowserChannel["CHROMIUM"] = "chromium";
242
+ BrowserChannel["CHROME"] = "chrome";
243
+ BrowserChannel["CHROME_BETA"] = "chrome-beta";
244
+ BrowserChannel["CHROME_DEV"] = "chrome-dev";
245
+ BrowserChannel["CHROME_CANARY"] = "chrome-canary";
246
+ BrowserChannel["MSEDGE"] = "msedge";
247
+ BrowserChannel["MSEDGE_BETA"] = "msedge-beta";
248
+ BrowserChannel["MSEDGE_DEV"] = "msedge-dev";
249
+ BrowserChannel["MSEDGE_CANARY"] = "msedge-canary";
250
+ })(BrowserChannel || (BrowserChannel = {}));
251
+ export const BROWSERUSE_DEFAULT_CHANNEL = BrowserChannel.CHROMIUM;
252
+ const DEFAULT_PERMISSIONS = [
253
+ 'clipboard-read',
254
+ 'clipboard-write',
255
+ 'notifications',
256
+ ];
257
+ const DEFAULT_IGNORE_ARGS = [
258
+ '--enable-automation',
259
+ '--disable-extensions',
260
+ '--hide-scrollbars',
261
+ '--disable-features=AcceptCHFrame,AutoExpandDetailsElement,AvoidUnnecessaryBeforeUnloadCheckSync,CertificateTransparencyComponentUpdater,DeferRendererTasksAfterInput,DestroyProfileOnBrowserClose,DialMediaRouteProvider,ExtensionManifestV2Disabled,GlobalMediaControls,HttpsUpgrades,ImprovedCookieControls,LazyFrameLoading,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate',
262
+ ];
263
+ const DEFAULT_BROWSER_PROFILE_OPTIONS = {
264
+ accept_downloads: true,
265
+ offline: false,
266
+ strict_selectors: false,
267
+ proxy: null,
268
+ permissions: DEFAULT_PERMISSIONS.slice(),
269
+ bypass_csp: false,
270
+ client_certificates: [],
271
+ extra_http_headers: {},
272
+ http_credentials: null,
273
+ ignore_https_errors: false,
274
+ java_script_enabled: true,
275
+ base_url: null,
276
+ service_workers: ServiceWorkers.ALLOW,
277
+ user_agent: null,
278
+ screen: null,
279
+ viewport: null,
280
+ no_viewport: null,
281
+ device_scale_factor: null,
282
+ is_mobile: false,
283
+ has_touch: false,
284
+ locale: null,
285
+ geolocation: null,
286
+ timezone_id: null,
287
+ color_scheme: ColorScheme.LIGHT,
288
+ contrast: Contrast.NO_PREFERENCE,
289
+ reduced_motion: ReducedMotion.NO_PREFERENCE,
290
+ forced_colors: ForcedColors.NONE,
291
+ record_har_content: RecordHarContent.EMBED,
292
+ record_har_mode: RecordHarMode.FULL,
293
+ record_har_omit_content: false,
294
+ record_har_path: null,
295
+ record_har_url_filter: null,
296
+ record_video_dir: null,
297
+ record_video_size: null,
298
+ headers: null,
299
+ slow_mo: 0,
300
+ timeout: 30000,
301
+ env: null,
302
+ executable_path: null,
303
+ headless: null,
304
+ args: [],
305
+ ignore_default_args: DEFAULT_IGNORE_ARGS.slice(),
306
+ channel: null,
307
+ chromium_sandbox: !CONFIG.IN_DOCKER,
308
+ devtools: false,
309
+ downloads_path: null,
310
+ traces_dir: null,
311
+ handle_sighup: true,
312
+ handle_sigint: false,
313
+ handle_sigterm: false,
314
+ id: uuid7str(),
315
+ user_data_dir: CONFIG.BROWSER_USE_DEFAULT_USER_DATA_DIR,
316
+ storage_state: null,
317
+ stealth: false,
318
+ disable_security: false,
319
+ deterministic_rendering: false,
320
+ allowed_domains: null,
321
+ keep_alive: null,
322
+ enable_default_extensions: true,
323
+ window_size: null,
324
+ window_height: null,
325
+ window_width: null,
326
+ window_position: { width: 0, height: 0 },
327
+ default_navigation_timeout: null,
328
+ default_timeout: null,
329
+ minimum_wait_page_load_time: 0.25,
330
+ wait_for_network_idle_page_load_time: 0.5,
331
+ maximum_wait_page_load_time: 5.0,
332
+ wait_between_actions: 0.5,
333
+ include_dynamic_attributes: true,
334
+ highlight_elements: true,
335
+ viewport_expansion: 500,
336
+ profile_directory: 'Default',
337
+ cookies_file: null,
338
+ };
339
+ const argsAsDict = (args) => {
340
+ const result = {};
341
+ for (const arg of args) {
342
+ const [keyPart, valuePart = ''] = arg.split('=', 1);
343
+ const key = keyPart.trim().replace(/^-+/, '');
344
+ result[key] = valuePart.trim();
345
+ }
346
+ return result;
347
+ };
348
+ const argsAsList = (args) => Object.entries(args).map(([key, value]) => value
349
+ ? `--${key.replace(/^-+/, '')}=${value}`
350
+ : `--${key.replace(/^-+/, '')}`);
351
+ const cloneDefaultOptions = () => JSON.parse(JSON.stringify(DEFAULT_BROWSER_PROFILE_OPTIONS));
352
+ export class BrowserProfile {
353
+ options;
354
+ constructor(init = {}) {
355
+ const defaults = cloneDefaultOptions();
356
+ this.options = {
357
+ ...defaults,
358
+ ...init,
359
+ permissions: init.permissions
360
+ ? [...init.permissions]
361
+ : defaults.permissions,
362
+ client_certificates: init.client_certificates
363
+ ? [...init.client_certificates]
364
+ : [],
365
+ extra_http_headers: init.extra_http_headers
366
+ ? { ...init.extra_http_headers }
367
+ : {},
368
+ args: init.args ? init.args.map(validate_cli_arg) : [],
369
+ ignore_default_args: Array.isArray(init.ignore_default_args)
370
+ ? init.ignore_default_args.map(validate_cli_arg)
371
+ : (init.ignore_default_args ?? defaults.ignore_default_args),
372
+ window_position: init.window_position ?? defaults.window_position,
373
+ };
374
+ this.options.id = init.id ?? uuid7str();
375
+ this.applyLegacyWindowSize();
376
+ this.warnStorageStateUserDataDirConflict();
377
+ this.warnUserDataDirNonDefault();
378
+ this.warnDeterministicRenderingWeirdness();
379
+ }
380
+ toString() {
381
+ return `BrowserProfile#${this.options.id.slice(-4)}`;
382
+ }
383
+ describe() {
384
+ const shortDir = this.options.user_data_dir
385
+ ? log_pretty_path(this.options.user_data_dir)
386
+ : '<incognito>';
387
+ return `BrowserProfile#${this.options.id.slice(-4)}(user_data_dir=${shortDir}, headless=${this.options.headless})`;
388
+ }
389
+ get config() {
390
+ return this.options;
391
+ }
392
+ // Public getters for commonly accessed properties
393
+ get allowed_domains() {
394
+ return this.options.allowed_domains;
395
+ }
396
+ get cookies_file() {
397
+ return this.options.cookies_file;
398
+ }
399
+ get default_navigation_timeout() {
400
+ return this.options.default_navigation_timeout;
401
+ }
402
+ get downloads_path() {
403
+ return this.options.downloads_path;
404
+ }
405
+ get highlight_elements() {
406
+ return this.options.highlight_elements;
407
+ }
408
+ get keep_alive() {
409
+ return this.options.keep_alive;
410
+ }
411
+ set keep_alive(value) {
412
+ this.options.keep_alive = value;
413
+ }
414
+ get maximum_wait_page_load_time() {
415
+ return this.options.maximum_wait_page_load_time;
416
+ }
417
+ get traces_dir() {
418
+ return this.options.traces_dir;
419
+ }
420
+ get user_data_dir() {
421
+ return this.options.user_data_dir;
422
+ }
423
+ get viewport_expansion() {
424
+ return this.options.viewport_expansion;
425
+ }
426
+ get viewport() {
427
+ return this.options.viewport;
428
+ }
429
+ get wait_for_network_idle_page_load_time() {
430
+ return this.options.wait_for_network_idle_page_load_time;
431
+ }
432
+ get window_size() {
433
+ return this.options.window_size;
434
+ }
435
+ applyLegacyWindowSize() {
436
+ const { window_width, window_height } = this.options;
437
+ if (window_width || window_height) {
438
+ logger.warning('⚠️ BrowserProfile(window_width=..., window_height=...) are deprecated, use BrowserProfile(window_size={"width": 1280, "height": 1100}) instead.');
439
+ const newSize = {
440
+ ...(this.options.window_size ?? { width: 0, height: 0 }),
441
+ };
442
+ newSize.width = newSize.width || window_width || 1280;
443
+ newSize.height = newSize.height || window_height || 1100;
444
+ this.options.window_size = newSize;
445
+ }
446
+ }
447
+ warnStorageStateUserDataDirConflict() {
448
+ const hasStorageState = this.options.storage_state !== null;
449
+ const hasUserDataDir = Boolean(this.options.user_data_dir &&
450
+ !this.options.user_data_dir.toLowerCase().includes('tmp'));
451
+ const hasCookiesFile = this.options.cookies_file !== null;
452
+ const staticSource = hasCookiesFile
453
+ ? 'cookies_file'
454
+ : hasStorageState
455
+ ? 'storage_state'
456
+ : null;
457
+ if (staticSource && hasUserDataDir) {
458
+ logger.warning(`⚠️ BrowserSession(...) was passed both ${staticSource} AND user_data_dir. ${staticSource}=${this.options.storage_state ?? this.options.cookies_file} will forcibly overwrite cookies/localStorage/sessionStorage in user_data_dir=${this.options.user_data_dir}. For multiple browsers in parallel, use only storage_state with user_data_dir=None, or use a separate user_data_dir for each browser and set storage_state=None.`);
459
+ }
460
+ }
461
+ warnUserDataDirNonDefault() {
462
+ const isNotDefault = Boolean(this.options.executable_path ||
463
+ (this.options.channel &&
464
+ this.options.channel !== BROWSERUSE_DEFAULT_CHANNEL));
465
+ if (this.options.user_data_dir === CONFIG.BROWSER_USE_DEFAULT_USER_DATA_DIR &&
466
+ isNotDefault) {
467
+ const alternateName = this.options.executable_path
468
+ ? path
469
+ .basename(this.options.executable_path)
470
+ .toLowerCase()
471
+ .replace(/ /g, '-')
472
+ : this.options.channel
473
+ ? this.options.channel.toLowerCase()
474
+ : 'none';
475
+ logger.warning(`⚠️ ${this} Changing user_data_dir=${log_pretty_path(this.options.user_data_dir)} ➡️ .../default-${alternateName} to avoid ${alternateName.toUpperCase()} corruping default profile created by ${BROWSERUSE_DEFAULT_CHANNEL}`);
476
+ const dir = path.dirname(CONFIG.BROWSER_USE_DEFAULT_USER_DATA_DIR);
477
+ this.options.user_data_dir = path.join(dir, `default-${alternateName}`);
478
+ }
479
+ }
480
+ warnDeterministicRenderingWeirdness() {
481
+ if (this.options.deterministic_rendering) {
482
+ logger.warning('⚠️ BrowserSession(deterministic_rendering=True) is NOT RECOMMENDED. It breaks many sites and increases chances of getting blocked by anti-bot systems. It hardcodes the JS random seed and forces browsers across Linux/Mac/Windows to use the same font rendering engine so that identical screenshots can be generated.');
483
+ }
484
+ }
485
+ getDefaultArgsList() {
486
+ const ignore = this.options.ignore_default_args;
487
+ if (Array.isArray(ignore)) {
488
+ const ignoreSet = new Set(ignore);
489
+ return CHROME_DEFAULT_ARGS.filter((arg) => !ignoreSet.has(arg));
490
+ }
491
+ if (ignore === true) {
492
+ return [];
493
+ }
494
+ return [...CHROME_DEFAULT_ARGS];
495
+ }
496
+ getWindowSizeArgs() {
497
+ const args = [];
498
+ const size = this.options.window_size;
499
+ if (size && size.width && size.height) {
500
+ args.push(`--window-size=${size.width},${size.height}`);
501
+ }
502
+ else if (!this.options.headless) {
503
+ args.push('--start-maximized');
504
+ }
505
+ return args;
506
+ }
507
+ getWindowPositionArgs() {
508
+ const args = [];
509
+ const position = this.options.window_position;
510
+ if (position &&
511
+ typeof position.width === 'number' &&
512
+ typeof position.height === 'number') {
513
+ args.push(`--window-position=${position.width},${position.height}`);
514
+ }
515
+ return args;
516
+ }
517
+ async getExtensionArgs() {
518
+ const extensionPaths = await this.ensureDefaultExtensionsDownloaded();
519
+ const args = [
520
+ '--enable-extensions',
521
+ '--disable-extensions-file-access-check',
522
+ '--disable-extensions-http-throttling',
523
+ '--enable-extension-activity-logging',
524
+ ];
525
+ if (extensionPaths.length) {
526
+ args.push(`--load-extension=${extensionPaths.join(',')}`);
527
+ }
528
+ return args;
529
+ }
530
+ async ensureDefaultExtensionsDownloaded() {
531
+ const cacheDir = CONFIG.BROWSER_USE_EXTENSIONS_DIR;
532
+ await fsp.mkdir(cacheDir, { recursive: true });
533
+ const extensionPaths = [];
534
+ const loadedNames = [];
535
+ for (const ext of DEFAULT_EXTENSIONS) {
536
+ const extDir = path.join(cacheDir, ext.id);
537
+ const manifestPath = path.join(extDir, 'manifest.json');
538
+ if (fs.existsSync(extDir) && fs.existsSync(manifestPath)) {
539
+ extensionPaths.push(extDir);
540
+ loadedNames.push(ext.name);
541
+ continue;
542
+ }
543
+ const crxFile = path.join(cacheDir, `${ext.id}.crx`);
544
+ try {
545
+ if (!fs.existsSync(crxFile)) {
546
+ logger.info(`📦 Downloading ${ext.name} extension...`);
547
+ await this.downloadExtension(ext.url, crxFile);
548
+ }
549
+ if (fs.existsSync(crxFile)) {
550
+ logger.info(`📂 Extracting ${ext.name} extension...`);
551
+ await this.extractExtension(crxFile, extDir);
552
+ extensionPaths.push(extDir);
553
+ loadedNames.push(ext.name);
554
+ }
555
+ }
556
+ catch (error) {
557
+ logger.warning(`⚠️ Failed to setup ${ext.name} extension: ${error.message}`);
558
+ }
559
+ }
560
+ if (extensionPaths.length) {
561
+ logger.info(`✅ Extensions ready: ${extensionPaths.length} extensions loaded (${loadedNames.join(', ')})`);
562
+ }
563
+ else {
564
+ logger.warning('⚠️ No default extensions could be loaded');
565
+ }
566
+ return extensionPaths;
567
+ }
568
+ downloadExtension(url, outputPath, redirectCount = 0) {
569
+ const maxRedirects = 5;
570
+ return new Promise((resolve, reject) => {
571
+ https
572
+ .get(url, (response) => {
573
+ const { statusCode, headers } = response;
574
+ if (statusCode &&
575
+ statusCode >= 300 &&
576
+ statusCode < 400 &&
577
+ headers.location &&
578
+ redirectCount < maxRedirects) {
579
+ response.resume();
580
+ this.downloadExtension(headers.location, outputPath, redirectCount + 1)
581
+ .then(resolve)
582
+ .catch(reject);
583
+ return;
584
+ }
585
+ if (!statusCode || statusCode >= 400) {
586
+ reject(new Error(`Failed to download extension (status ${statusCode ?? 'unknown'})`));
587
+ return;
588
+ }
589
+ const chunks = [];
590
+ response.on('data', (chunk) => chunks.push(chunk));
591
+ response.on('end', async () => {
592
+ try {
593
+ await fsp.writeFile(outputPath, Buffer.concat(chunks));
594
+ resolve();
595
+ }
596
+ catch (error) {
597
+ reject(error);
598
+ }
599
+ });
600
+ })
601
+ .on('error', reject);
602
+ });
603
+ }
604
+ async extractExtension(crxPath, extractDir) {
605
+ if (fs.existsSync(extractDir)) {
606
+ await fsp.rm(extractDir, { recursive: true, force: true });
607
+ }
608
+ await fsp.mkdir(extractDir, { recursive: true });
609
+ const buffer = await fsp.readFile(crxPath);
610
+ try {
611
+ const zip = new AdmZip(buffer);
612
+ zip.extractAllTo(extractDir, true);
613
+ }
614
+ catch {
615
+ const zipBuffer = this.stripCrxHeader(buffer);
616
+ const zip = new AdmZip(zipBuffer);
617
+ zip.extractAllTo(extractDir, true);
618
+ }
619
+ if (!fs.existsSync(path.join(extractDir, 'manifest.json'))) {
620
+ throw new Error('No manifest.json found in extension');
621
+ }
622
+ }
623
+ stripCrxHeader(buffer) {
624
+ const magic = buffer.subarray(0, 4).toString();
625
+ if (magic !== 'Cr24') {
626
+ throw new Error('Invalid CRX file format');
627
+ }
628
+ const version = buffer.readUInt32LE(4);
629
+ if (version === 2) {
630
+ const pubkeyLen = buffer.readUInt32LE(8);
631
+ const sigLen = buffer.readUInt32LE(12);
632
+ const offset = 16 + pubkeyLen + sigLen;
633
+ return buffer.subarray(offset);
634
+ }
635
+ if (version === 3) {
636
+ const headerLen = buffer.readUInt32LE(8);
637
+ const offset = 12 + headerLen;
638
+ return buffer.subarray(offset);
639
+ }
640
+ throw new Error(`Unsupported CRX version: ${version}`);
641
+ }
642
+ async getArgs() {
643
+ const defaultArgs = this.getDefaultArgsList();
644
+ const preConversionArgs = [
645
+ ...defaultArgs,
646
+ ...this.options.args,
647
+ `--profile-directory=${this.options.profile_directory}`,
648
+ ...(CONFIG.IN_DOCKER || !this.options.chromium_sandbox
649
+ ? CHROME_DOCKER_ARGS
650
+ : []),
651
+ ...(this.options.headless ? CHROME_HEADLESS_ARGS : []),
652
+ ...(this.options.disable_security ? CHROME_DISABLE_SECURITY_ARGS : []),
653
+ ...(this.options.deterministic_rendering
654
+ ? CHROME_DETERMINISTIC_RENDERING_ARGS
655
+ : []),
656
+ ...this.getWindowSizeArgs(),
657
+ ...this.getWindowPositionArgs(),
658
+ ...(this.options.enable_default_extensions
659
+ ? await this.getExtensionArgs()
660
+ : []),
661
+ ];
662
+ const finalArgs = argsAsList(argsAsDict(preConversionArgs));
663
+ return finalArgs;
664
+ }
665
+ async detect_display_configuration() {
666
+ const runner = observe_debug({
667
+ name: 'detect_display_configuration',
668
+ ignore_input: true,
669
+ ignore_output: true,
670
+ })(async () => {
671
+ const displaySize = get_display_size();
672
+ const hasScreen = Boolean(displaySize);
673
+ this.options.screen = this.options.screen ||
674
+ displaySize || { width: 1280, height: 1100 };
675
+ if (this.options.headless === null) {
676
+ this.options.headless = !hasScreen;
677
+ }
678
+ if (this.options.headless) {
679
+ this.options.viewport =
680
+ this.options.viewport ||
681
+ this.options.window_size ||
682
+ this.options.screen;
683
+ this.options.window_position = null;
684
+ this.options.window_size = null;
685
+ this.options.no_viewport = false;
686
+ }
687
+ else {
688
+ this.options.window_size =
689
+ this.options.window_size || this.options.screen;
690
+ this.options.no_viewport = this.options.no_viewport ?? true;
691
+ this.options.viewport = this.options.no_viewport
692
+ ? null
693
+ : this.options.viewport;
694
+ }
695
+ let useViewport = Boolean(this.options.headless) ||
696
+ Boolean(this.options.viewport) ||
697
+ Boolean(this.options.device_scale_factor);
698
+ if (this.options.no_viewport === null) {
699
+ this.options.no_viewport = !useViewport;
700
+ }
701
+ useViewport = !this.options.no_viewport;
702
+ if (useViewport) {
703
+ this.options.viewport = this.options.viewport ||
704
+ this.options.screen || { width: 1280, height: 1100 };
705
+ this.options.device_scale_factor =
706
+ this.options.device_scale_factor || 1.0;
707
+ }
708
+ else {
709
+ this.options.viewport = null;
710
+ this.options.device_scale_factor = null;
711
+ this.options.screen = null;
712
+ }
713
+ if (this.options.headless && this.options.no_viewport) {
714
+ throw new Error('headless=True and no_viewport=True cannot both be set at the same time');
715
+ }
716
+ });
717
+ return runner.call(this);
718
+ }
719
+ cloneContextArgs() {
720
+ const o = this.options;
721
+ return {
722
+ accept_downloads: o.accept_downloads,
723
+ offline: o.offline,
724
+ strict_selectors: o.strict_selectors,
725
+ proxy: o.proxy ? { ...o.proxy } : null,
726
+ permissions: [...o.permissions],
727
+ bypass_csp: o.bypass_csp,
728
+ client_certificates: o.client_certificates
729
+ ? [...o.client_certificates]
730
+ : [],
731
+ extra_http_headers: { ...o.extra_http_headers },
732
+ http_credentials: o.http_credentials ? { ...o.http_credentials } : null,
733
+ ignore_https_errors: o.ignore_https_errors,
734
+ java_script_enabled: o.java_script_enabled,
735
+ base_url: o.base_url,
736
+ service_workers: o.service_workers,
737
+ user_agent: o.user_agent,
738
+ screen: o.screen ? { ...o.screen } : null,
739
+ viewport: o.viewport ? { ...o.viewport } : null,
740
+ no_viewport: o.no_viewport,
741
+ device_scale_factor: o.device_scale_factor,
742
+ is_mobile: o.is_mobile,
743
+ has_touch: o.has_touch,
744
+ locale: o.locale,
745
+ geolocation: o.geolocation ? { ...o.geolocation } : null,
746
+ timezone_id: o.timezone_id,
747
+ color_scheme: o.color_scheme,
748
+ contrast: o.contrast,
749
+ reduced_motion: o.reduced_motion,
750
+ forced_colors: o.forced_colors,
751
+ record_har_content: o.record_har_content,
752
+ record_har_mode: o.record_har_mode,
753
+ record_har_omit_content: o.record_har_omit_content,
754
+ record_har_path: o.record_har_path,
755
+ record_har_url_filter: o.record_har_url_filter,
756
+ record_video_dir: o.record_video_dir,
757
+ record_video_size: o.record_video_size
758
+ ? { ...o.record_video_size }
759
+ : null,
760
+ };
761
+ }
762
+ cloneLaunchArgs(args) {
763
+ const o = this.options;
764
+ return {
765
+ env: o.env ? { ...o.env } : null,
766
+ executable_path: o.executable_path,
767
+ headless: o.headless,
768
+ args,
769
+ ignore_default_args: Array.isArray(o.ignore_default_args)
770
+ ? [...o.ignore_default_args]
771
+ : o.ignore_default_args,
772
+ channel: o.channel,
773
+ chromium_sandbox: o.chromium_sandbox,
774
+ devtools: o.devtools,
775
+ slow_mo: o.slow_mo,
776
+ timeout: o.timeout,
777
+ proxy: o.proxy ? { ...o.proxy } : null,
778
+ downloads_path: o.downloads_path,
779
+ traces_dir: o.traces_dir,
780
+ handle_sighup: o.handle_sighup,
781
+ handle_sigint: o.handle_sigint,
782
+ handle_sigterm: o.handle_sigterm,
783
+ };
784
+ }
785
+ kwargs_for_new_context() {
786
+ return {
787
+ ...this.cloneContextArgs(),
788
+ storage_state: this.options.storage_state
789
+ ? typeof this.options.storage_state === 'string'
790
+ ? this.options.storage_state
791
+ : { ...this.options.storage_state }
792
+ : null,
793
+ };
794
+ }
795
+ kwargs_for_connect() {
796
+ return {
797
+ headers: this.options.headers ? { ...this.options.headers } : null,
798
+ slow_mo: this.options.slow_mo,
799
+ timeout: this.options.timeout,
800
+ };
801
+ }
802
+ async kwargs_for_launch() {
803
+ const args = await this.getArgs();
804
+ return this.cloneLaunchArgs(args);
805
+ }
806
+ async kwargs_for_launch_persistent_context() {
807
+ const args = await this.getArgs();
808
+ return {
809
+ ...this.cloneContextArgs(),
810
+ ...this.cloneLaunchArgs(args),
811
+ user_data_dir: this.options.user_data_dir,
812
+ };
813
+ }
814
+ }
815
+ export const DEFAULT_BROWSER_PROFILE = new BrowserProfile();