n8n-nodes-browser-use
Version:
n8n node to control browser-use AI-powered browser automation with Nodes-as-Tools support
475 lines • 22.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BrowserUse = void 0;
const n8n_workflow_1 = require("n8n-workflow");
class BrowserUse {
constructor() {
this.description = {
displayName: 'Browser Use',
name: 'browserUse',
icon: 'file:icons/browseruse.svg',
group: ['transform'],
version: 1,
description: 'Automate browser interactions using AI',
usableAsTool: true,
defaults: {
name: 'Browser Use',
},
inputs: ['main'],
outputs: ['main'],
credentials: [
{
name: 'browserUseCloudApi',
required: true,
displayOptions: {
show: {
connectionType: ['cloud'],
},
},
},
{
name: 'browserUseLocalBridgeApi',
required: true,
displayOptions: {
show: {
connectionType: ['local'],
},
},
},
],
properties: [
{
displayName: 'Connection Type',
name: 'connectionType',
type: 'options',
options: [
{
name: 'Cloud API',
value: 'cloud',
description: 'Connect to Browser Use Cloud API (simplest setup)',
},
{
name: 'Local Bridge',
value: 'local',
description: 'Connect to locally running Browser Use bridge (requires additional setup)',
},
],
default: 'cloud',
description: 'Choose how to connect to Browser Use',
},
{
displayName: 'Local Bridge Setup Required',
name: 'localBridgeNotice',
type: 'notice',
default: 'The Local Bridge option requires setting up a Python service separately. Please refer to the documentation for installation instructions.',
displayOptions: {
show: {
connectionType: ['local'],
},
},
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Get Task',
value: 'getTask',
description: 'Retrieve detailed information about a specific browser automation task',
action: 'Retrieve detailed information about a specific browser automation task',
},
{
name: 'Get Task Media',
value: 'getTaskMedia',
description: 'Retrieve media (screenshot, video, or PDF) captured during a browser task',
action: 'Retrieve media screenshot video or pdf captured during a browser task',
},
{
name: 'Get Task Status',
value: 'getTaskStatus',
description: 'Check the current status of a running or completed browser task',
action: 'Check the current status of a running or completed browser task',
},
{
name: 'List Tasks',
value: 'listTasks',
description: 'List all browser automation tasks with pagination support',
action: 'List all browser automation tasks with pagination support',
},
{
name: 'Pause Task',
value: 'pauseTask',
description: 'Temporarily pause a running browser automation task',
action: 'Temporarily pause a running browser automation task',
},
{
name: 'Resume Task',
value: 'resumeTask',
description: 'Resume a previously paused browser automation task',
action: 'Resume a previously paused browser automation task',
},
{
name: 'Run Task',
value: 'runTask',
description: 'Execute a new browser automation task with natural language instructions',
action: 'Execute a new browser automation task with natural language instructions',
},
{
name: 'Stop Task',
value: 'stopTask',
description: 'Completely stop and terminate a browser automation task',
action: 'Completely stop and terminate a browser automation task',
},
],
default: 'runTask',
},
{
displayName: 'Instructions',
name: 'instructions',
type: 'string',
typeOptions: {
rows: 5,
},
default: '',
placeholder: 'e.g., Go to google.com and search for "n8n automation"',
displayOptions: {
show: {
operation: ['runTask'],
},
},
description: 'Natural language instructions for the browser to follow. For example: "Go to amazon.com, search for wireless headphones, and extract the prices and ratings of the first 5 results". You can use $fromAI() to dynamically populate this field from AI Agent input.',
required: true,
hint: 'The browser will follow these instructions autonomously, performing actions like navigating, clicking, typing, and data extraction.',
},
{
displayName: 'AI Provider',
name: 'aiProvider',
type: 'options',
options: [
{ name: 'Anthropic', value: 'anthropic', description: 'Use Anthropic models like Claude' },
{ name: 'Azure OpenAI', value: 'azure', description: 'Use Azure-hosted OpenAI models' },
{ name: 'Google', value: 'google', description: 'Use Google Gemini models' },
{ name: 'Mistral', value: 'mistral', description: 'Use Mistral AI models' },
{ name: 'Ollama', value: 'ollama', description: 'Use locally-hosted Ollama models' },
{ name: 'OpenAI', value: 'openai', description: 'Use OpenAI models like GPT-4o' },
],
default: 'openai',
description: 'The AI provider to use for processing browser instructions',
displayOptions: {
show: {
operation: ['runTask'],
connectionType: ['local'],
},
},
},
{
displayName: 'Save Browser Data',
name: 'saveBrowserData',
type: 'boolean',
default: false,
displayOptions: {
show: {
operation: ['runTask'],
connectionType: ['cloud'],
},
},
description: 'Whether to save browser cookies and session data for future tasks. Useful for maintaining login sessions across multiple tasks.',
},
{
displayName: 'Headful Mode',
name: 'headful',
type: 'boolean',
default: false,
displayOptions: {
show: {
operation: ['runTask'],
connectionType: ['local'],
},
},
description: 'Whether to run the browser in visible (headful) mode. When enabled, you will see the browser window as it performs actions.',
},
{
displayName: 'Use Custom Chrome',
name: 'useCustomChrome',
type: 'boolean',
default: true,
displayOptions: {
show: {
operation: ['runTask'],
connectionType: ['local'],
},
},
description: 'Whether to use a custom Chrome installation specified in environment variables. Disable if you want to use the default system Chrome.',
},
{
displayName: 'Task ID',
name: 'taskId',
type: 'string',
default: '',
displayOptions: {
show: {
operation: ['getTaskStatus', 'stopTask', 'getTaskMedia', 'getTask', 'pauseTask', 'resumeTask'],
},
},
description: 'The unique identifier of the browser task to interact with',
required: true,
},
{
displayName: 'Media Type',
name: 'mediaType',
type: 'options',
options: [
{ name: 'Screenshot', value: 'screenshot', description: 'A static image of the current browser view' },
{ name: 'Video', value: 'video', description: 'A video recording of the browser automation session' },
{ name: 'PDF', value: 'pdf', description: 'A PDF export of the current page' },
],
default: 'screenshot',
displayOptions: {
show: {
operation: ['getTaskMedia'],
},
},
description: 'The type of media to retrieve from the browser task',
},
{
displayName: 'Limit',
name: 'limit',
type: 'number',
typeOptions: {
minValue: 1,
},
default: 50,
displayOptions: {
show: {
operation: ['listTasks'],
},
},
description: 'Max number of results to return',
}
],
};
}
async execute() {
const items = this.getInputData();
const returnData = [];
const operation = this.getNodeParameter('operation', 0);
const connectionType = this.getNodeParameter('connectionType', 0);
let credentials;
let baseUrl;
try {
if (connectionType === 'cloud') {
credentials = await this.getCredentials('browserUseCloudApi');
if (!credentials.apiKey) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'API Key is required for Browser Use Cloud API');
}
baseUrl = 'https://api.browser-use.com/api/v1';
try {
await this.helpers.request({
method: 'GET',
url: `${baseUrl}/ping`,
headers: {
'Authorization': `Bearer ${credentials.apiKey}`,
},
json: true,
});
}
catch (error) {
throw new n8n_workflow_1.NodeApiError(this.getNode(), error, { message: `Failed to connect to Browser Use Cloud API: ${error.message}` });
}
}
else {
credentials = await this.getCredentials('browserUseLocalBridgeApi');
if (!credentials.url) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'URL is required for Browser Use Local Bridge');
}
baseUrl = credentials.url;
if (!baseUrl.endsWith('/api/v1')) {
baseUrl = `${baseUrl}/api/v1`.replace(/\/+/g, '/');
}
try {
await this.helpers.request({
method: 'GET',
url: `${baseUrl}/ping`,
headers: {
'Authorization': credentials.token ? `Bearer ${credentials.token}` : undefined,
},
json: true,
});
}
catch (error) {
throw new n8n_workflow_1.NodeApiError(this.getNode(), error, { message: `Failed to connect to Browser Use Local Bridge at ${baseUrl}: ${error.message}` });
}
}
for (let i = 0; i < items.length; i++) {
try {
if (operation === 'runTask') {
const instructions = this.getNodeParameter('instructions', i);
let saveBrowserData = false;
if (connectionType === 'cloud') {
saveBrowserData = this.getNodeParameter('saveBrowserData', i);
}
const body = {
task: instructions,
};
if (connectionType === 'cloud') {
body.save_browser_data = saveBrowserData;
}
else {
const aiProvider = this.getNodeParameter('aiProvider', i);
body.ai_provider = aiProvider;
body.headful = this.getNodeParameter('headful', i);
body.use_custom_chrome = this.getNodeParameter('useCustomChrome', i);
}
const response = await this.helpers.request({
method: 'POST',
url: `${baseUrl}/run-task`,
headers: {
'Authorization': connectionType === 'cloud'
? `Bearer ${credentials.apiKey}`
: credentials.token ? `Bearer ${credentials.token}` : undefined,
'Content-Type': 'application/json',
},
body,
json: true,
});
returnData.push({
json: response,
});
}
else if (operation === 'getTaskStatus') {
const taskId = this.getNodeParameter('taskId', i);
const response = await this.helpers.request({
method: 'GET',
url: `${baseUrl}/task/${taskId}/status`,
headers: {
'Authorization': connectionType === 'cloud'
? `Bearer ${credentials.apiKey}`
: credentials.token ? `Bearer ${credentials.token}` : undefined,
},
json: true,
});
returnData.push({
json: response,
});
}
else if (operation === 'stopTask') {
const taskId = this.getNodeParameter('taskId', i);
const response = await this.helpers.request({
method: 'PUT',
url: `${baseUrl}/stop-task/${taskId}`,
headers: {
'Authorization': connectionType === 'cloud'
? `Bearer ${credentials.apiKey}`
: credentials.token ? `Bearer ${credentials.token}` : undefined,
},
json: true,
});
returnData.push({
json: response,
});
}
else if (operation === 'getTaskMedia') {
const taskId = this.getNodeParameter('taskId', i);
const mediaType = this.getNodeParameter('mediaType', i);
const response = await this.helpers.request({
method: 'GET',
url: `${baseUrl}/task/${taskId}/media?type=${mediaType}`,
headers: {
'Authorization': connectionType === 'cloud'
? `Bearer ${credentials.apiKey}`
: credentials.token ? `Bearer ${credentials.token}` : undefined,
},
json: true,
});
returnData.push({
json: response,
});
}
else if (operation === 'getTask') {
const taskId = this.getNodeParameter('taskId', i);
const response = await this.helpers.request({
method: 'GET',
url: `${baseUrl}/task/${taskId}`,
headers: {
'Authorization': connectionType === 'cloud'
? `Bearer ${credentials.apiKey}`
: credentials.token ? `Bearer ${credentials.token}` : undefined,
},
json: true,
});
returnData.push({
json: response,
});
}
else if (operation === 'pauseTask') {
const taskId = this.getNodeParameter('taskId', i);
const response = await this.helpers.request({
method: 'PUT',
url: `${baseUrl}/pause-task/${taskId}`,
headers: {
'Authorization': connectionType === 'cloud'
? `Bearer ${credentials.apiKey}`
: credentials.token ? `Bearer ${credentials.token}` : undefined,
},
json: true,
});
returnData.push({
json: response,
});
}
else if (operation === 'resumeTask') {
const taskId = this.getNodeParameter('taskId', i);
const response = await this.helpers.request({
method: 'PUT',
url: `${baseUrl}/resume-task/${taskId}`,
headers: {
'Authorization': connectionType === 'cloud'
? `Bearer ${credentials.apiKey}`
: credentials.token ? `Bearer ${credentials.token}` : undefined,
},
json: true,
});
returnData.push({
json: response,
});
}
else if (operation === 'listTasks') {
const limit = this.getNodeParameter('limit', i);
let queryString = `limit=${limit}`;
const response = await this.helpers.request({
method: 'GET',
url: `${baseUrl}/tasks?${queryString}`,
headers: {
'Authorization': connectionType === 'cloud'
? `Bearer ${credentials.apiKey}`
: credentials.token ? `Bearer ${credentials.token}` : undefined,
},
json: true,
});
returnData.push({
json: response,
});
}
}
catch (error) {
if (this.continueOnFail()) {
returnData.push({ json: { error: error.message } });
continue;
}
throw error;
}
}
}
catch (error) {
if (this.continueOnFail()) {
return [[{ json: { error: error.message } }]];
}
throw error;
}
return [returnData];
}
}
exports.BrowserUse = BrowserUse;
//# sourceMappingURL=BrowserUse.node.js.map