Kernel Profiles API
Create, list, retrieve, and delete browser profiles.
Create, list, retrieve, and delete browser profiles.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/kernel-profiles-api"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
openapi: 3.1.0
info:
title: Kernel API Keys Profiles API
description: Developer tools and cloud infrastructure for AI agents to use web browsers
version: 0.1.0
servers:
- url: https://api.onkernel.com
description: API Server
security:
- bearerAuth: []
tags:
- name: Profiles
description: Create, list, retrieve, and delete browser profiles.
paths:
/profiles:
post:
operationId: postProfiles
tags:
- Profiles
summary: Create a new profile
description: Create a browser profile that can be used to load state into future browser sessions.
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ProfileRequest'
responses:
'201':
description: Profile created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Profile'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'409':
$ref: '#/components/responses/Conflict'
'500':
$ref: '#/components/responses/InternalError'
x-codeSamples:
- lang: JavaScript
source: "import Kernel from '@onkernel/sdk';\n\nconst client = new Kernel({\n apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted\n});\n\nconst profile = await client.profiles.create();\n\nconsole.log(profile.id);"
- lang: Python
source: "import os\nfrom kernel import Kernel\n\nclient = Kernel(\n api_key=os.environ.get(\"KERNEL_API_KEY\"), # This is the default and can be omitted\n)\nprofile = client.profiles.create()\nprint(profile.id)"
- lang: Go
source: "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/kernel/kernel-go-sdk\"\n\t\"github.com/kernel/kernel-go-sdk/option\"\n)\n\nfunc main() {\n\tclient := kernel.NewClient(\n\t\toption.WithAPIKey(\"My API Key\"),\n\t)\n\tprofile, err := client.Profiles.New(context.TODO(), kernel.ProfileNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf(\"%+v\\n\", profile.ID)\n}\n"
get:
operationId: getProfiles
tags:
- Profiles
summary: List profiles
description: List profiles with optional filtering and pagination.
security:
- bearerAuth: []
parameters:
- name: limit
in: query
required: false
description: Limit the number of profiles to return.
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: offset
in: query
required: false
description: Offset the number of profiles to return.
schema:
type: integer
minimum: 0
default: 0
- name: query
in: query
required: false
description: Case-insensitive substring match against profile name or ID.
schema:
type: string
- name: name
in: query
required: false
description: Exact-match filter on profile name using the database collation. In production, matching is case- and accent-insensitive. During the default-project migration, unscoped requests prefer a concrete default-project profile over a legacy unscoped profile with the same name.
schema:
type: string
responses:
'200':
description: List of profiles
headers:
X-Limit:
description: Limit the number of profiles to return.
schema:
type: integer
minimum: 1
maximum: 100
default: 20
X-Offset:
description: The offset of profiles to return.
schema:
type: integer
minimum: 0
default: 0
X-Next-Offset:
description: The offset where the next page starts. 0 when there are no more results.
schema:
type: integer
nullable: true
X-Has-More:
description: Whether there are more profiles to fetch.
schema:
type: boolean
default: false
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Profile'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalError'
x-codeSamples:
- lang: JavaScript
source: "import Kernel from '@onkernel/sdk';\n\nconst client = new Kernel({\n apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const profile of client.profiles.list()) {\n console.log(profile.id);\n}"
- lang: Python
source: "import os\nfrom kernel import Kernel\n\nclient = Kernel(\n api_key=os.environ.get(\"KERNEL_API_KEY\"), # This is the default and can be omitted\n)\npage = client.profiles.list()\npage = page.items[0]\nprint(page.id)"
- lang: Go
source: "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/kernel/kernel-go-sdk\"\n\t\"github.com/kernel/kernel-go-sdk/option\"\n)\n\nfunc main() {\n\tclient := kernel.NewClient(\n\t\toption.WithAPIKey(\"My API Key\"),\n\t)\n\tpage, err := client.Profiles.List(context.TODO(), kernel.ProfileListParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf(\"%+v\\n\", page)\n}\n"
/profiles/{id_or_name}:
get:
operationId: getProfileByIdOrName
tags:
- Profiles
summary: Get profile by ID or name
description: Retrieve details for a single profile by its ID or name.
security:
- bearerAuth: []
parameters:
- name: id_or_name
in: path
required: true
schema:
type: string
description: Profile ID or name
responses:
'200':
description: Profile details
content:
application/json:
schema:
$ref: '#/components/schemas/Profile'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalError'
x-codeSamples:
- lang: JavaScript
source: "import Kernel from '@onkernel/sdk';\n\nconst client = new Kernel({\n apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted\n});\n\nconst profile = await client.profiles.retrieve('id_or_name');\n\nconsole.log(profile.id);"
- lang: Python
source: "import os\nfrom kernel import Kernel\n\nclient = Kernel(\n api_key=os.environ.get(\"KERNEL_API_KEY\"), # This is the default and can be omitted\n)\nprofile = client.profiles.retrieve(\n \"id_or_name\",\n)\nprint(profile.id)"
- lang: Go
source: "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/kernel/kernel-go-sdk\"\n\t\"github.com/kernel/kernel-go-sdk/option\"\n)\n\nfunc main() {\n\tclient := kernel.NewClient(\n\t\toption.WithAPIKey(\"My API Key\"),\n\t)\n\tprofile, err := client.Profiles.Get(context.TODO(), \"id_or_name\")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf(\"%+v\\n\", profile.ID)\n}\n"
patch:
operationId: patchProfileByIdOrName
tags:
- Profiles
summary: Rename profile by ID or name
description: Update a profile's name. Names must be unique within the logical project; during the default-project migration, unscoped profiles and profiles in the org default project are treated as the same project. Duplicate-name conflicts are checked before update but are best-effort because there is no backing unique index. Renaming a profile while a browser session references it by name may prevent that session's changes from saving; prefer renaming when the profile is not in use.
security:
- bearerAuth: []
parameters:
- name: id_or_name
in: path
required: true
schema:
type: string
description: Profile ID or profile name
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ProfileUpdateRequest'
responses:
'200':
description: Profile updated
content:
application/json:
schema:
$ref: '#/components/schemas/Profile'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
'500':
$ref: '#/components/responses/InternalError'
x-codeSamples:
- lang: JavaScript
source: "import Kernel from '@onkernel/sdk';\n\nconst client = new Kernel({\n apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted\n});\n\nconst profile = await client.profiles.update('id_or_name', { name: 'my-renamed-profile' });\n\nconsole.log(profile.id);"
- lang: Python
source: "import os\nfrom kernel import Kernel\n\nclient = Kernel(\n api_key=os.environ.get(\"KERNEL_API_KEY\"), # This is the default and can be omitted\n)\nprofile = client.profiles.update(\n id_or_name=\"id_or_name\",\n name=\"my-renamed-profile\",\n)\nprint(profile.id)"
- lang: Go
source: "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/kernel/kernel-go-sdk\"\n\t\"github.com/kernel/kernel-go-sdk/option\"\n)\n\nfunc main() {\n\tclient := kernel.NewClient(\n\t\toption.WithAPIKey(\"My API Key\"),\n\t)\n\tprofile, err := client.Profiles.Update(\n\t\tcontext.TODO(),\n\t\t\"id_or_name\",\n\t\tkernel.ProfileUpdateParams{\n\t\t\tName: \"my-renamed-profile\",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf(\"%+v\\n\", profile.ID)\n}\n"
delete:
operationId: deleteProfileByIdOrName
tags:
- Profiles
summary: Delete profile by ID or name
description: Delete a profile by its ID or by its name.
security:
- bearerAuth: []
parameters:
- name: id_or_name
in: path
required: true
schema:
type: string
description: Profile ID or profile name
responses:
'204':
description: Profile deleted successfully
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalError'
x-codeSamples:
- lang: JavaScript
source: "import Kernel from '@onkernel/sdk';\n\nconst client = new Kernel({\n apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted\n});\n\nawait client.profiles.delete('id_or_name');"
- lang: Python
source: "import os\nfrom kernel import Kernel\n\nclient = Kernel(\n api_key=os.environ.get(\"KERNEL_API_KEY\"), # This is the default and can be omitted\n)\nclient.profiles.delete(\n \"id_or_name\",\n)"
- lang: Go
source: "package main\n\nimport (\n\t\"context\"\n\n\t\"github.com/kernel/kernel-go-sdk\"\n\t\"github.com/kernel/kernel-go-sdk/option\"\n)\n\nfunc main() {\n\tclient := kernel.NewClient(\n\t\toption.WithAPIKey(\"My API Key\"),\n\t)\n\terr := client.Profiles.Delete(context.TODO(), \"id_or_name\")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n"
/profiles/{id_or_name}/download:
get:
operationId: downloadProfileByIdOrName
tags:
- Profiles
summary: Download profile archive
description: Returns a zstd-compressed tar file of the full user-data directory.
security:
- bearerAuth: []
parameters:
- name: id_or_name
in: path
required: true
schema:
type: string
description: Profile ID or name
responses:
'200':
description: zstd-compressed tar archive of the user-data directory
content:
application/octet-stream:
schema:
type: string
format: binary
'202':
description: Profile exists but has not yet captured any state. Use it in a browser session first to capture state.
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalError'
x-codeSamples:
- lang: JavaScript
source: "import Kernel from '@onkernel/sdk';\n\nconst client = new Kernel({\n apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted\n});\n\nconst response = await client.profiles.download('id_or_name');\n\nconsole.log(response);\n\nconst content = await response.blob();\nconsole.log(content);"
- lang: Python
source: "import os\nfrom kernel import Kernel\n\nclient = Kernel(\n api_key=os.environ.get(\"KERNEL_API_KEY\"), # This is the default and can be omitted\n)\nresponse = client.profiles.download(\n \"id_or_name\",\n)\nprint(response)\ncontent = response.read()\nprint(content)"
- lang: Go
source: "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/kernel/kernel-go-sdk\"\n\t\"github.com/kernel/kernel-go-sdk/option\"\n)\n\nfunc main() {\n\tclient := kernel.NewClient(\n\t\toption.WithAPIKey(\"My API Key\"),\n\t)\n\tresponse, err := client.Profiles.Download(context.TODO(), \"id_or_name\")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf(\"%+v\\n\", response)\n}\n"
components:
responses:
Conflict:
description: Conflict – resource already exists
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
InternalError:
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Unauthorized:
description: Unauthorized – missing or invalid authorization token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
BadRequest:
description: Bad Request – invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
NotFound:
description: Resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Forbidden:
description: Forbidden – insufficient permissions or plan
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
schemas:
Error:
type: object
required:
- code
- message
properties:
code:
type: string
description: Application-specific error code (machine-readable)
example: bad_request
message:
type: string
description: Human-readable error description for debugging
example: 'Missing required field: app_name'
details:
type: array
description: Additional error details (for multiple errors)
items:
$ref: '#/components/schemas/ErrorDetail'
inner_error:
$ref: '#/components/schemas/ErrorDetail'
ProfileRequest:
type: object
description: Request body for creating a profile.
properties:
name:
type: string
description: Optional name of the profile. Must be unique within the logical project; during the default-project migration, unscoped profiles and profiles in the org default project are treated as the same project.
required: []
ProfileUpdateRequest:
type: object
required:
- name
properties:
name:
type: string
description: New profile name. Must be unique within the logical project; during the default-project migration, unscoped profiles and profiles in the org default project are treated as the same project.
minLength: 1
maxLength: 255
example: my-renamed-profile
Profile:
type: object
description: Browser profile metadata.
properties:
id:
type: string
description: Unique identifier for the profile
name:
type: string
nullable: true
description: Optional, easier-to-reference name for the profile
created_at:
type: string
format: date-time
description: Timestamp when the profile was created
updated_at:
type: string
format: date-time
description: Timestamp when the profile was last updated
last_used_at:
type: string
format: date-time
description: Timestamp when the profile was last used
required:
- id
- created_at
ErrorDetail:
type: object
properties:
code:
type: string
description: Lower-level error code providing more specific detail
example: invalid_input
message:
type: string
description: Further detail about the error
example: Provided version string is not semver compliant
securitySchemes:
bearerAuth:
type: http
scheme: bearer