functions
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBrowserbase Functions Skill
Browserbase Functions 技能
Guide Claude through deploying serverless browser automation using the official CLI.
bb指导你使用官方 CLI部署无服务器浏览器自动化。
bbWhen to Use
适用场景
Use this skill when:
- User wants to deploy automation to run on a schedule
- User needs a webhook endpoint for browser automation
- User wants to run automation in the cloud (not locally)
- User asks about Browserbase Functions
在以下场景使用本技能:
- 用户想要部署可按计划运行的自动化任务
- 用户需要用于浏览器自动化的Webhook端点
- 用户希望在云端(而非本地)运行自动化任务
- 用户询问Browserbase Functions相关内容
Prerequisites
前置条件
1. Get Credentials
1. 获取凭证
Get API key and Project ID from: https://browserbase.com/settings
从以下地址获取API密钥和项目ID:https://browserbase.com/settings
2. Set Environment Variables
2. 设置环境变量
Set directly:
bash
export BROWSERBASE_API_KEY="your_api_key"
export BROWSERBASE_PROJECT_ID="your_project_id"直接设置:
bash
export BROWSERBASE_API_KEY="your_api_key"
export BROWSERBASE_PROJECT_ID="your_project_id"Creating a Function Project
创建函数项目
1. Initialize with Official CLI
1. 使用官方CLI初始化
bash
pnpm dlx @browserbasehq/sdk-functions init my-function
cd my-functionThis creates:
my-function/
├── package.json
├── index.ts # Your function code
└── .env # Add credentials herebash
pnpm dlx @browserbasehq/sdk-functions init my-function
cd my-function此命令会创建如下结构:
my-function/
├── package.json
├── index.ts # 你的函数代码
└── .env # 在此添加凭证2. Add Credentials to .env
2. 将凭证添加到.env文件
bash
undefinedbash
undefinedCopy from stored credentials
从已存储的凭证中复制
echo "BROWSERBASE_API_KEY=$BROWSERBASE_API_KEY" >> .env
echo "BROWSERBASE_PROJECT_ID=$BROWSERBASE_PROJECT_ID" >> .env
Or manually edit `.env`:BROWSERBASE_API_KEY=your_api_key
BROWSERBASE_PROJECT_ID=your_project_id
undefinedecho "BROWSERBASE_API_KEY=$BROWSERBASE_API_KEY" >> .env
echo "BROWSERBASE_PROJECT_ID=$BROWSERBASE_PROJECT_ID" >> .env
或者手动编辑`.env`:BROWSERBASE_API_KEY=your_api_key
BROWSERBASE_PROJECT_ID=your_project_id
undefined3. Install Dependencies
3. 安装依赖
bash
pnpm installbash
pnpm installFunction Structure
函数结构
typescript
import { defineFn } from "@browserbasehq/sdk-functions";
import { chromium } from "playwright-core";
defineFn("my-function", async (context) => {
const { session, params } = context;
// Connect to browser
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
// Your automation
await page.goto(params.url || "https://example.com");
const title = await page.title();
// Return JSON-serializable result
return { success: true, title };
});Key objects:
- - CDP endpoint to connect Playwright
context.session.connectUrl - - Input parameters from invocation
context.params
typescript
import { defineFn } from "@browserbasehq/sdk-functions";
import { chromium } from "playwright-core";
defineFn("my-function", async (context) => {
const { session, params } = context;
// 连接到浏览器
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
// 你的自动化逻辑
await page.goto(params.url || "https://example.com");
const title = await page.title();
// 返回可序列化为JSON的结果
return { success: true, title };
});关键对象:
- - 用于连接Playwright的CDP端点
context.session.connectUrl - - 调用时传入的输入参数
context.params
Development Workflow
开发工作流
1. Start Dev Server
1. 启动开发服务器
bash
pnpm bb dev index.tsServer runs at
http://127.0.0.1:14113bash
pnpm bb dev index.ts服务器运行在
http://127.0.0.1:141132. Test Locally
2. 本地测试
bash
curl -X POST http://127.0.0.1:14113/v1/functions/my-function/invoke \
-H "Content-Type: application/json" \
-d '{"params": {"url": "https://news.ycombinator.com"}}'bash
curl -X POST http://127.0.0.1:14113/v1/functions/my-function/invoke \
-H "Content-Type: application/json" \
-d '{"params": {"url": "https://news.ycombinator.com"}}'3. Iterate
3. 迭代开发
The dev server auto-reloads on file changes. Use for debugging - output appears in the terminal.
console.log()开发服务器会在文件变更时自动重载。使用进行调试,输出会显示在终端中。
console.log()Deploying
部署
Publish to Browserbase
发布到Browserbase
bash
pnpm bb publish index.tsOutput:
Function published successfully
Build ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Function ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxSave the Function ID - you need it to invoke.
bash
pnpm bb publish index.ts输出示例:
Function published successfully
Build ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Function ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx请保存Function ID - 调用函数时需要用到它。
Invoking Deployed Functions
调用已部署的函数
Via curl
使用curl
bash
undefinedbash
undefinedStart invocation
发起调用
curl -X POST "https://api.browserbase.com/v1/functions/FUNCTION_ID/invoke"
-H "Content-Type: application/json"
-H "x-bb-api-key: $BROWSERBASE_API_KEY"
-d '{"params": {"url": "https://example.com"}}'
-H "Content-Type: application/json"
-H "x-bb-api-key: $BROWSERBASE_API_KEY"
-d '{"params": {"url": "https://example.com"}}'
curl -X POST "https://api.browserbase.com/v1/functions/FUNCTION_ID/invoke"
-H "Content-Type: application/json"
-H "x-bb-api-key: $BROWSERBASE_API_KEY"
-d '{"params": {"url": "https://example.com"}}'
-H "Content-Type: application/json"
-H "x-bb-api-key: $BROWSERBASE_API_KEY"
-d '{"params": {"url": "https://example.com"}}'
Response: {"id": "INVOCATION_ID"}
响应: {"id": "INVOCATION_ID"}
Poll for result
轮询获取结果
curl "https://api.browserbase.com/v1/functions/invocations/INVOCATION_ID"
-H "x-bb-api-key: $BROWSERBASE_API_KEY"
-H "x-bb-api-key: $BROWSERBASE_API_KEY"
undefinedcurl "https://api.browserbase.com/v1/functions/invocations/INVOCATION_ID"
-H "x-bb-api-key: $BROWSERBASE_API_KEY"
-H "x-bb-api-key: $BROWSERBASE_API_KEY"
undefinedVia Code
使用代码调用
typescript
async function invokeFunction(functionId: string, params: object) {
// Start invocation
const invokeRes = await fetch(
`https://api.browserbase.com/v1/functions/${functionId}/invoke`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-bb-api-key': process.env.BROWSERBASE_API_KEY!,
},
body: JSON.stringify({ params }),
}
);
const { id: invocationId } = await invokeRes.json();
// Poll until complete
while (true) {
await new Promise(r => setTimeout(r, 5000));
const statusRes = await fetch(
`https://api.browserbase.com/v1/functions/invocations/${invocationId}`,
{ headers: { 'x-bb-api-key': process.env.BROWSERBASE_API_KEY! } }
);
const result = await statusRes.json();
if (result.status === 'COMPLETED') return result.results;
if (result.status === 'FAILED') throw new Error(result.error);
}
}typescript
async function invokeFunction(functionId: string, params: object) {
// 发起调用
const invokeRes = await fetch(
`https://api.browserbase.com/v1/functions/${functionId}/invoke`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-bb-api-key': process.env.BROWSERBASE_API_KEY!,
},
body: JSON.stringify({ params }),
}
);
const { id: invocationId } = await invokeRes.json();
// 轮询直到完成
while (true) {
await new Promise(r => setTimeout(r, 5000));
const statusRes = await fetch(
`https://api.browserbase.com/v1/functions/invocations/${invocationId}`,
{ headers: { 'x-bb-api-key': process.env.BROWSERBASE_API_KEY! } }
);
const result = await statusRes.json();
if (result.status === 'COMPLETED') return result.results;
if (result.status === 'FAILED') throw new Error(result.error);
}
}Common Patterns
常见模式
Parameterized Scraping
参数化爬取
typescript
defineFn("scrape", async ({ session, params }) => {
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
await page.goto(params.url);
await page.waitForSelector(params.selector);
const items = await page.$$eval(params.selector, els =>
els.map(el => el.textContent?.trim())
);
return { url: params.url, items };
});typescript
defineFn("scrape", async ({ session, params }) => {
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
await page.goto(params.url);
await page.waitForSelector(params.selector);
const items = await page.$$eval(params.selector, els =>
els.map(el => el.textContent?.trim())
);
return { url: params.url, items };
});With Authentication
带身份验证的场景
typescript
defineFn("authenticated-action", async ({ session, params }) => {
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
// Login
await page.goto("https://example.com/login");
await page.fill('[name="email"]', params.email);
await page.fill('[name="password"]', params.password);
await page.click('button[type="submit"]');
await page.waitForURL('**/dashboard');
// Do authenticated work
const data = await page.textContent('.user-data');
return { data };
});typescript
defineFn("authenticated-action", async ({ session, params }) => {
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
// 登录
await page.goto("https://example.com/login");
await page.fill('[name="email"]', params.email);
await page.fill('[name="password"]', params.password);
await page.click('button[type="submit"]');
await page.waitForURL('**/dashboard');
// 执行需身份验证的操作
const data = await page.textContent('.user-data');
return { data };
});Error Handling
错误处理
typescript
defineFn("safe-scrape", async ({ session, params }) => {
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
try {
await page.goto(params.url, { timeout: 30000 });
await page.waitForSelector(params.selector, { timeout: 10000 });
const data = await page.textContent(params.selector);
return { success: true, data };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
});typescript
defineFn("safe-scrape", async ({ session, params }) => {
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
try {
await page.goto(params.url, { timeout: 30000 });
await page.waitForSelector(params.selector, { timeout: 10000 });
const data = await page.textContent(params.selector);
return { success: true, data };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
});CLI Reference
CLI 参考
| Command | Description |
|---|---|
| Create new project |
| Start local dev server |
| Deploy to Browserbase |
| 命令 | 描述 |
|---|---|
| 创建新项目 |
| 启动本地开发服务器 |
| 部署到Browserbase |
Troubleshooting
故障排除
"Missing API key"
"Missing API key"(缺少API密钥)
bash
undefinedbash
undefinedCheck .env file has credentials
检查.env文件是否包含凭证
cat .env
cat .env
Or set for current shell
或者为当前Shell设置环境变量
export BROWSERBASE_API_KEY="your_key"
export BROWSERBASE_PROJECT_ID="your_project"
undefinedexport BROWSERBASE_API_KEY="your_key"
export BROWSERBASE_PROJECT_ID="your_project"
undefinedDev server won't start
开发服务器无法启动
bash
undefinedbash
undefinedMake sure SDK is installed
确保已安装SDK
pnpm add @browserbasehq/sdk-functions
pnpm add @browserbasehq/sdk-functions
Or use npx
或者使用npx
npx @browserbasehq/sdk-functions dev index.ts
undefinednpx @browserbasehq/sdk-functions dev index.ts
undefinedFunction times out
函数超时
- Max execution time is 15 minutes
- Add specific timeouts to page operations
- Use instead of sleep
waitForSelector
- 最大执行时间为15分钟
- 为页面操作添加特定的超时设置
- 使用而非sleep
waitForSelector
Can't connect to browser
无法连接到浏览器
- Check is being used correctly
session.connectUrl - Ensure you're using not
chromium.connectOverCDP()chromium.launch()
- 检查是否正确使用
session.connectUrl - 确保你使用的是而非
chromium.connectOverCDP()chromium.launch()