关于 kernel-python-sdk
面向使用 Kernel 管理浏览器会话的 Python 开发者技能,涵盖服务端 Playwright、CDP、配置文件、代理和会话清理。
主要功能
- 01服务端 Playwright 执行
- 02客户端通过 CDP 使用 Playwright
- 03持久化浏览器配置文件
- 04显式代理路由
- 05浏览器会话生命周期指引
适用场景
- 01在浏览器 VM 中运行 Playwright
- 02使用本地 Playwright 工具调试
- 03保留 Cookie 和配置文件状态
- 04通过代理路由会话
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ kernel/ skills --skill kernel-python-sdk安装后在 Claude Code 中输入/kernel-python-sdk确认已加载。
附带文件examples/examples.md
详细介绍
适用场景
使用此技能编写用于创建和控制 Kernel 浏览器会话的 Python 代码。以下场景优先使用此技能:
- 在浏览器 VM 中运行服务端 Playwright
- 通过 CDP 使用客户端 Playwright
- 使用持久化配置文件和显式代理路由
- 浏览器池或已部署的 Python 操作
使用 kernel-cli 技能执行 Shell 命令和快速的一次性会话。
设置
uv pip install -U kernel
# Add this only for client-side CDP:
uv pip install playwright
在环境中设置 KERNEL_API_KEY;不要将其写入源代码。Kernel() 和 AsyncKernel() 会自动读取它。始终使用异步客户端——不要在异步操作中调用同步 SDK 方法。
选择自动化路径
服务端 Playwright(默认)
在 Chrome 旁运行 JavaScript/TypeScript。这样可以避免本地 CDP 往返,也不需要本地 Playwright:
from kernel import Kernel
with Kernel() as client:
browser = client.browsers.create(stealth=True, timeout_seconds=300)
try:
response = client.browsers.playwright.execute(
browser.session_id,
code="""
await page.goto("https://example.com");
return { title: await page.title(), url: page.url() };
""",
timeout_sec=60,
)
if not response.success:
raise RuntimeError(response.error or response.stderr or "Playwright execution failed")
print(response.result)
finally:
client.browsers.delete_by_id(browser.session_id)
将会话 ID 作为第一个位置参数传入。代码会收到 page、context 和 browser。请使用 return;否则 response.result 为空。timeout_sec 限制远程代码执行时间,而 SDK 的 timeout= 选项控制 HTTP 请求。
通过 CDP 使用客户端 Playwright
需要本地 Playwright 工具或交互式调试时,使用 CDP:
import asyncio
from kernel import AsyncKernel
from playwright.async_api import async_playwright
async def main() -> None:
async with AsyncKernel() as client:
kernel_browser = await client.browsers.create(
stealth=True,
timeout_seconds=300,
)
try:
async with async_playwright() as playwright:
remote = await playwright.chromium.connect_over_cdp(
kernel_browser.cdp_ws_url
)
context = remote.contexts[0]
page = context.pages[0] if context.pages else await context.new_page()
await page.goto("https://example.com")
print(await page.title())
finally:
await client.browsers.delete_by_id(kernel_browser.session_id)
asyncio.run(main())
复用现有默认上下文,以便页面能看到 Kernel 会话已加载的配置文件状态;新的隐身上下文不会共享该状态。SDK 客户端上下文会关闭 HTTP 连接,但不会代替删除远程浏览器。
浏览器生命周期和清理
- 每次创建或获取会话后,立即用
try/finally包裹。 - 使用
client.browsers.delete_by_id(session_id)删除普通会话;使用AsyncKernel时请加上await。 - 通过浏览器池获取的会话,应使用浏览器池释放 API 释放,而不是删除。
- 即使有清理逻辑,也应将浏览器不活动超时设为有限值。活动操作可能延长该超时,因此它不能代替显式清理。
- 只有在所有使用临时配置文件和代理的会话都结束后,才删除这些配置文件和代理。保留有意设置的持久化配置文件。
配置文件
先创建配置文件,再附加使用。需要将 Cookie 和本地状态持久化回配置文件时,设置 save_changes=True:
profile = client.profiles.create(name="checkout-login")
browser = client.browsers.create(
profile={"id": profile.id, "save_changes": True},
stealth=True,
)
try:
# Automate with server-side Playwright or CDP.
...
finally:
client.browsers.delete_by_id(browser.session_id)
删除浏览器会结束会话,并允许配置文件更改最终写入。不要先删除配置文件。使用 {"id": ...} 或 {"name": ...} 其中之一,不要同时使用。
Python SDK 可以请求任一归档格式,并原生重命名配置文件:
archive = client.profiles.download(profile.id, format="tar")
archive.write_to_file("profile.tar")
client.profiles.update(profile.id, name="checkout-login-v2")
SDK 会为 tar.zst 和 tar 两种格式写入归档;它不会解压归档内容。需要将归档解压到目录时,使用 kernel profiles download <id-or-name> --to ./profile。
代理和默认隐身代理
创建时使用 proxy_id 附加显式代理:
proxy = client.proxies.create(
type="datacenter",
config={"country": "US"},
name="automation-us",
)
try:
client.proxies.check(proxy.id, url="https://example.com")
browser = client.browsers.create(stealth=True, proxy_id=proxy.id)
try:
...
finally:
client.browsers.delete_by_id(browser.session_id)
finally:
client.proxies.delete(proxy.id) # Only if this proxy was created for this run.
针对特定目标的代理检查会验证该公共 HTTP/HTTPS URL。对于住宅和移动代理,此检查不能保证浏览器之后会使用相同的出口节点;对于自定义 URL,此检查也不会更新常规代理健康状态。
可以更改运行中浏览器的代理路由:
client.browsers.update(browser.session_id, proxy_id=another_proxy_id)
client.browsers.update(browser.session_id, proxy_id="") # Remove explicit proxy.
未附加显式代理时,隐身浏览器可能会使用 Kernel 的默认隐身代理。可单独控制此代理:
client.browsers.update(browser.session_id, disable_default_proxy=True) # Direct connection
client.browsers.update(browser.session_id, disable_default_proxy=False) # Re-enable default
disable_default_proxy 是更新参数,不是浏览器创建参数。当前 SDK 不支持重命名代理;请使用 kernel proxies update <id> --name <new-name>。要更改代理名称以外的任何内容,请重新创建代理。
已部署操作模式
from typing import TypedDict
import kernel
app = kernel.App("app-name")
class TaskInput(TypedDict):
task: str
@app.action("action-name")
async def run(ctx: kernel.KernelContext, payload: TaskInput):
async with kernel.AsyncKernel() as client:
browser = await client.browsers.create(
invocation_id=ctx.invocation_id,
timeout_seconds=300,
)
try:
response = await client.browsers.playwright.execute(
browser.session_id,
code="return await page.title();",
)
if not response.success:
raise RuntimeError(response.error or response.stderr or "Playwright execution failed")
return response.result
finally:
await client.browsers.delete_by_id(browser.session_id)
二进制结果
服务端截图和 PDF 可能会返回 Node.js Buffer 形状的结果:
response = client.browsers.playwright.execute(
browser.session_id,
code="return await page.screenshot({ fullPage: true });",
)
if response.success and response.result:
with open("output.png", "wb") as file:
file.write(bytes(response.result["data"]))