From 8c0ce1c1533a538483419f4da0937a6153eb5273 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 27 May 2026 20:48:05 +0000
Subject: [PATCH 01/10] feat: Support Byteful mobile proxies
---
.stats.yml | 4 +-
src/kernel/types/proxy_check_response.py | 77 +--------------------
src/kernel/types/proxy_create_params.py | 75 +-------------------
src/kernel/types/proxy_create_response.py | 77 +--------------------
src/kernel/types/proxy_list_response.py | 77 +--------------------
src/kernel/types/proxy_retrieve_response.py | 77 +--------------------
6 files changed, 12 insertions(+), 375 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 3cfc09d4..834590a5 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 117
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-3b34d85c005a4058ac1faaea092615af577d12cee6e420f102de57339251672d.yml
-openapi_spec_hash: fad386b8e8712e6639ed9689e9dfc070
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a32ac633a8f67f3844b6ccb7b97687aec2cf2e2c611df4157c223dfac16db806.yml
+openapi_spec_hash: f8c9aabe60372f28ad9cceed42009274
config_hash: 0f222358f24700d1811c5d27078a3849
diff --git a/src/kernel/types/proxy_check_response.py b/src/kernel/types/proxy_check_response.py
index c26d665d..f3cdab80 100644
--- a/src/kernel/types/proxy_check_response.py
+++ b/src/kernel/types/proxy_check_response.py
@@ -59,87 +59,14 @@ class ConfigResidentialProxyConfig(BaseModel):
class ConfigMobileProxyConfig(BaseModel):
"""Configuration for mobile proxies."""
- asn: Optional[str] = None
- """Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html"""
-
- carrier: Optional[
- Literal[
- "a1",
- "aircel",
- "airtel",
- "att",
- "celcom",
- "chinamobile",
- "claro",
- "comcast",
- "cox",
- "digi",
- "dt",
- "docomo",
- "dtac",
- "etisalat",
- "idea",
- "kyivstar",
- "meo",
- "megafon",
- "mtn",
- "mtnza",
- "mts",
- "optus",
- "orange",
- "qwest",
- "reliance_jio",
- "robi",
- "sprint",
- "telefonica",
- "telstra",
- "tmobile",
- "tigo",
- "tim",
- "verizon",
- "vimpelcom",
- "vodacomza",
- "vodafone",
- "vivo",
- "zain",
- "vivabo",
- "telenormyanmar",
- "kcelljsc",
- "swisscom",
- "singtel",
- "asiacell",
- "windit",
- "cellc",
- "ooredoo",
- "drei",
- "umobile",
- "cableone",
- "proximus",
- "tele2",
- "mobitel",
- "o2",
- "bouygues",
- "free",
- "sfr",
- "digicel",
- ]
- ] = None
- """Mobile carrier."""
-
city: Optional[str] = None
- """City name (no spaces, e.g.
-
- `sanfrancisco`). If provided, `country` must also be provided.
- """
+ """Provider city alias. Mobile carrier routing can make observed geo vary."""
country: Optional[str] = None
"""ISO 3166 country code"""
state: Optional[str] = None
- """Two-letter state code."""
-
- zip: Optional[str] = None
- """US ZIP code."""
+ """US-only state code. Mobile carrier routing can make observed geo vary."""
class ConfigCustomProxyConfig(BaseModel):
diff --git a/src/kernel/types/proxy_create_params.py b/src/kernel/types/proxy_create_params.py
index 175b95ff..331bd776 100644
--- a/src/kernel/types/proxy_create_params.py
+++ b/src/kernel/types/proxy_create_params.py
@@ -81,85 +81,14 @@ class ConfigResidentialProxyConfig(TypedDict, total=False):
class ConfigMobileProxyConfig(TypedDict, total=False):
"""Configuration for mobile proxies."""
- asn: str
- """Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html"""
-
- carrier: Literal[
- "a1",
- "aircel",
- "airtel",
- "att",
- "celcom",
- "chinamobile",
- "claro",
- "comcast",
- "cox",
- "digi",
- "dt",
- "docomo",
- "dtac",
- "etisalat",
- "idea",
- "kyivstar",
- "meo",
- "megafon",
- "mtn",
- "mtnza",
- "mts",
- "optus",
- "orange",
- "qwest",
- "reliance_jio",
- "robi",
- "sprint",
- "telefonica",
- "telstra",
- "tmobile",
- "tigo",
- "tim",
- "verizon",
- "vimpelcom",
- "vodacomza",
- "vodafone",
- "vivo",
- "zain",
- "vivabo",
- "telenormyanmar",
- "kcelljsc",
- "swisscom",
- "singtel",
- "asiacell",
- "windit",
- "cellc",
- "ooredoo",
- "drei",
- "umobile",
- "cableone",
- "proximus",
- "tele2",
- "mobitel",
- "o2",
- "bouygues",
- "free",
- "sfr",
- "digicel",
- ]
- """Mobile carrier."""
-
city: str
- """City name (no spaces, e.g.
-
- `sanfrancisco`). If provided, `country` must also be provided.
- """
+ """Provider city alias. Mobile carrier routing can make observed geo vary."""
country: str
"""ISO 3166 country code"""
state: str
- """Two-letter state code."""
-
- zip: str
- """US ZIP code."""
+ """US-only state code. Mobile carrier routing can make observed geo vary."""
class ConfigCreateCustomProxyConfig(TypedDict, total=False):
diff --git a/src/kernel/types/proxy_create_response.py b/src/kernel/types/proxy_create_response.py
index d317662f..d71656c8 100644
--- a/src/kernel/types/proxy_create_response.py
+++ b/src/kernel/types/proxy_create_response.py
@@ -59,87 +59,14 @@ class ConfigResidentialProxyConfig(BaseModel):
class ConfigMobileProxyConfig(BaseModel):
"""Configuration for mobile proxies."""
- asn: Optional[str] = None
- """Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html"""
-
- carrier: Optional[
- Literal[
- "a1",
- "aircel",
- "airtel",
- "att",
- "celcom",
- "chinamobile",
- "claro",
- "comcast",
- "cox",
- "digi",
- "dt",
- "docomo",
- "dtac",
- "etisalat",
- "idea",
- "kyivstar",
- "meo",
- "megafon",
- "mtn",
- "mtnza",
- "mts",
- "optus",
- "orange",
- "qwest",
- "reliance_jio",
- "robi",
- "sprint",
- "telefonica",
- "telstra",
- "tmobile",
- "tigo",
- "tim",
- "verizon",
- "vimpelcom",
- "vodacomza",
- "vodafone",
- "vivo",
- "zain",
- "vivabo",
- "telenormyanmar",
- "kcelljsc",
- "swisscom",
- "singtel",
- "asiacell",
- "windit",
- "cellc",
- "ooredoo",
- "drei",
- "umobile",
- "cableone",
- "proximus",
- "tele2",
- "mobitel",
- "o2",
- "bouygues",
- "free",
- "sfr",
- "digicel",
- ]
- ] = None
- """Mobile carrier."""
-
city: Optional[str] = None
- """City name (no spaces, e.g.
-
- `sanfrancisco`). If provided, `country` must also be provided.
- """
+ """Provider city alias. Mobile carrier routing can make observed geo vary."""
country: Optional[str] = None
"""ISO 3166 country code"""
state: Optional[str] = None
- """Two-letter state code."""
-
- zip: Optional[str] = None
- """US ZIP code."""
+ """US-only state code. Mobile carrier routing can make observed geo vary."""
class ConfigCustomProxyConfig(BaseModel):
diff --git a/src/kernel/types/proxy_list_response.py b/src/kernel/types/proxy_list_response.py
index bbbe17c7..d1ddc079 100644
--- a/src/kernel/types/proxy_list_response.py
+++ b/src/kernel/types/proxy_list_response.py
@@ -60,87 +60,14 @@ class ProxyListResponseItemConfigResidentialProxyConfig(BaseModel):
class ProxyListResponseItemConfigMobileProxyConfig(BaseModel):
"""Configuration for mobile proxies."""
- asn: Optional[str] = None
- """Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html"""
-
- carrier: Optional[
- Literal[
- "a1",
- "aircel",
- "airtel",
- "att",
- "celcom",
- "chinamobile",
- "claro",
- "comcast",
- "cox",
- "digi",
- "dt",
- "docomo",
- "dtac",
- "etisalat",
- "idea",
- "kyivstar",
- "meo",
- "megafon",
- "mtn",
- "mtnza",
- "mts",
- "optus",
- "orange",
- "qwest",
- "reliance_jio",
- "robi",
- "sprint",
- "telefonica",
- "telstra",
- "tmobile",
- "tigo",
- "tim",
- "verizon",
- "vimpelcom",
- "vodacomza",
- "vodafone",
- "vivo",
- "zain",
- "vivabo",
- "telenormyanmar",
- "kcelljsc",
- "swisscom",
- "singtel",
- "asiacell",
- "windit",
- "cellc",
- "ooredoo",
- "drei",
- "umobile",
- "cableone",
- "proximus",
- "tele2",
- "mobitel",
- "o2",
- "bouygues",
- "free",
- "sfr",
- "digicel",
- ]
- ] = None
- """Mobile carrier."""
-
city: Optional[str] = None
- """City name (no spaces, e.g.
-
- `sanfrancisco`). If provided, `country` must also be provided.
- """
+ """Provider city alias. Mobile carrier routing can make observed geo vary."""
country: Optional[str] = None
"""ISO 3166 country code"""
state: Optional[str] = None
- """Two-letter state code."""
-
- zip: Optional[str] = None
- """US ZIP code."""
+ """US-only state code. Mobile carrier routing can make observed geo vary."""
class ProxyListResponseItemConfigCustomProxyConfig(BaseModel):
diff --git a/src/kernel/types/proxy_retrieve_response.py b/src/kernel/types/proxy_retrieve_response.py
index 6b0b1bbe..77d113e5 100644
--- a/src/kernel/types/proxy_retrieve_response.py
+++ b/src/kernel/types/proxy_retrieve_response.py
@@ -59,87 +59,14 @@ class ConfigResidentialProxyConfig(BaseModel):
class ConfigMobileProxyConfig(BaseModel):
"""Configuration for mobile proxies."""
- asn: Optional[str] = None
- """Autonomous system number. See https://bgp.potaroo.net/cidr/autnums.html"""
-
- carrier: Optional[
- Literal[
- "a1",
- "aircel",
- "airtel",
- "att",
- "celcom",
- "chinamobile",
- "claro",
- "comcast",
- "cox",
- "digi",
- "dt",
- "docomo",
- "dtac",
- "etisalat",
- "idea",
- "kyivstar",
- "meo",
- "megafon",
- "mtn",
- "mtnza",
- "mts",
- "optus",
- "orange",
- "qwest",
- "reliance_jio",
- "robi",
- "sprint",
- "telefonica",
- "telstra",
- "tmobile",
- "tigo",
- "tim",
- "verizon",
- "vimpelcom",
- "vodacomza",
- "vodafone",
- "vivo",
- "zain",
- "vivabo",
- "telenormyanmar",
- "kcelljsc",
- "swisscom",
- "singtel",
- "asiacell",
- "windit",
- "cellc",
- "ooredoo",
- "drei",
- "umobile",
- "cableone",
- "proximus",
- "tele2",
- "mobitel",
- "o2",
- "bouygues",
- "free",
- "sfr",
- "digicel",
- ]
- ] = None
- """Mobile carrier."""
-
city: Optional[str] = None
- """City name (no spaces, e.g.
-
- `sanfrancisco`). If provided, `country` must also be provided.
- """
+ """Provider city alias. Mobile carrier routing can make observed geo vary."""
country: Optional[str] = None
"""ISO 3166 country code"""
state: Optional[str] = None
- """Two-letter state code."""
-
- zip: Optional[str] = None
- """US ZIP code."""
+ """US-only state code. Mobile carrier routing can make observed geo vary."""
class ConfigCustomProxyConfig(BaseModel):
From 140eada5369eef70cedf56522cfcf9524f3d4062 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 29 May 2026 16:18:51 +0000
Subject: [PATCH 02/10] codegen metadata
---
.stats.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 834590a5..190a6ab6 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 117
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a32ac633a8f67f3844b6ccb7b97687aec2cf2e2c611df4157c223dfac16db806.yml
-openapi_spec_hash: f8c9aabe60372f28ad9cceed42009274
-config_hash: 0f222358f24700d1811c5d27078a3849
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-04da2c2ed5f83c54f59f6c148abcf013cc37282fde2b3b5b263dffab927d5ba2.yml
+openapi_spec_hash: 9b05d6877797e55051a83222fa7652d0
+config_hash: e0741f8035aea13f71e54e0fdb88eaa4
From 06a2f7babbc8f6ea31e46f3dfeb8d09dbaae88f0 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 29 May 2026 17:40:24 +0000
Subject: [PATCH 03/10] feat: api: surface category field on browser telemetry
events
---
.stats.yml | 4 ++--
src/kernel/types/browsers/browser_console_error_event.py | 2 ++
src/kernel/types/browsers/browser_console_log_event.py | 2 ++
src/kernel/types/browsers/browser_interaction_click_event.py | 2 ++
src/kernel/types/browsers/browser_interaction_key_event.py | 2 ++
.../browsers/browser_interaction_scroll_settled_event.py | 2 ++
.../types/browsers/browser_monitor_disconnected_event.py | 2 ++
.../types/browsers/browser_monitor_init_failed_event.py | 2 ++
.../types/browsers/browser_monitor_reconnect_failed_event.py | 2 ++
.../types/browsers/browser_monitor_reconnected_event.py | 2 ++
src/kernel/types/browsers/browser_monitor_screenshot_event.py | 2 ++
src/kernel/types/browsers/browser_network_idle_event.py | 2 ++
.../types/browsers/browser_network_loading_failed_event.py | 2 ++
src/kernel/types/browsers/browser_network_request_event.py | 2 ++
src/kernel/types/browsers/browser_network_response_event.py | 2 ++
.../types/browsers/browser_page_dom_content_loaded_event.py | 2 ++
.../types/browsers/browser_page_layout_settled_event.py | 2 ++
src/kernel/types/browsers/browser_page_layout_shift_event.py | 2 ++
src/kernel/types/browsers/browser_page_lcp_event.py | 2 ++
src/kernel/types/browsers/browser_page_load_event.py | 2 ++
src/kernel/types/browsers/browser_page_navigation_event.py | 2 ++
.../types/browsers/browser_page_navigation_settled_event.py | 2 ++
src/kernel/types/browsers/browser_page_tab_opened_event.py | 2 ++
23 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 190a6ab6..f41061ca 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 117
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-04da2c2ed5f83c54f59f6c148abcf013cc37282fde2b3b5b263dffab927d5ba2.yml
-openapi_spec_hash: 9b05d6877797e55051a83222fa7652d0
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-4bada2a5bdbde93018e5a1b1e80e134acbc5509cfdea94db6e4c5b799eba7b82.yml
+openapi_spec_hash: e0d541d480f5663b1e6bd3bb19a0fe61
config_hash: e0741f8035aea13f71e54e0fdb88eaa4
diff --git a/src/kernel/types/browsers/browser_console_error_event.py b/src/kernel/types/browsers/browser_console_error_event.py
index a152f944..72a93ede 100644
--- a/src/kernel/types/browsers/browser_console_error_event.py
+++ b/src/kernel/types/browsers/browser_console_error_event.py
@@ -65,6 +65,8 @@ class BrowserConsoleErrorEvent(BaseModel):
Emitted from two distinct CDP sources with different data shapes. Runtime.consoleAPICalled (console.error calls) produces level, text, args, and stack_trace. Runtime.exceptionThrown (uncaught exceptions) produces text, line, column, source_url, and stack_trace. Fields not applicable to the source are absent.
"""
+ category: Literal["console"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_console_log_event.py b/src/kernel/types/browsers/browser_console_log_event.py
index 5994c0be..338f6c85 100644
--- a/src/kernel/types/browsers/browser_console_log_event.py
+++ b/src/kernel/types/browsers/browser_console_log_event.py
@@ -42,6 +42,8 @@ class Data(BrowserEventContext):
class BrowserConsoleLogEvent(BaseModel):
"""A browser console log event (console.log, console.info, console.warn, etc.)."""
+ category: Literal["console"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_interaction_click_event.py b/src/kernel/types/browsers/browser_interaction_click_event.py
index efc76b34..7c4f6119 100644
--- a/src/kernel/types/browsers/browser_interaction_click_event.py
+++ b/src/kernel/types/browsers/browser_interaction_click_event.py
@@ -35,6 +35,8 @@ class Data(BrowserEventContext):
class BrowserInteractionClickEvent(BaseModel):
"""A browser user click event captured via injected page script."""
+ category: Literal["interaction"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_interaction_key_event.py b/src/kernel/types/browsers/browser_interaction_key_event.py
index e8860330..93f2c43e 100644
--- a/src/kernel/types/browsers/browser_interaction_key_event.py
+++ b/src/kernel/types/browsers/browser_interaction_key_event.py
@@ -29,6 +29,8 @@ class Data(BrowserEventContext):
class BrowserInteractionKeyEvent(BaseModel):
"""A browser keyboard event captured via injected page script."""
+ category: Literal["interaction"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_interaction_scroll_settled_event.py b/src/kernel/types/browsers/browser_interaction_scroll_settled_event.py
index 16b7536b..2c7ee24c 100644
--- a/src/kernel/types/browsers/browser_interaction_scroll_settled_event.py
+++ b/src/kernel/types/browsers/browser_interaction_scroll_settled_event.py
@@ -37,6 +37,8 @@ class BrowserInteractionScrollSettledEvent(BaseModel):
A browser scroll settled event emitted after scroll position stops changing, captured via injected page script.
"""
+ category: Literal["interaction"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_monitor_disconnected_event.py b/src/kernel/types/browsers/browser_monitor_disconnected_event.py
index b329ab13..ac37ec6a 100644
--- a/src/kernel/types/browsers/browser_monitor_disconnected_event.py
+++ b/src/kernel/types/browsers/browser_monitor_disconnected_event.py
@@ -20,6 +20,8 @@ class BrowserMonitorDisconnectedEvent(BaseModel):
Telemetry events may be dropped until monitor_reconnected arrives. Treat any in-progress computed state (network_idle, page_layout_settled) as unreliable until then.
"""
+ category: Literal["system"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_monitor_init_failed_event.py b/src/kernel/types/browsers/browser_monitor_init_failed_event.py
index a745fb8d..dba0e5da 100644
--- a/src/kernel/types/browsers/browser_monitor_init_failed_event.py
+++ b/src/kernel/types/browsers/browser_monitor_init_failed_event.py
@@ -17,6 +17,8 @@ class Data(BaseModel):
class BrowserMonitorInitFailedEvent(BaseModel):
"""The CDP session could not be initialized."""
+ category: Literal["system"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_monitor_reconnect_failed_event.py b/src/kernel/types/browsers/browser_monitor_reconnect_failed_event.py
index 79308d2e..57eec69b 100644
--- a/src/kernel/types/browsers/browser_monitor_reconnect_failed_event.py
+++ b/src/kernel/types/browsers/browser_monitor_reconnect_failed_event.py
@@ -23,6 +23,8 @@ class BrowserMonitorReconnectFailedEvent(BaseModel):
The CDP connection to Chrome could not be re-established after exhausting all reconnection attempts. No further telemetry events will arrive on this session.
"""
+ category: Literal["system"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_monitor_reconnected_event.py b/src/kernel/types/browsers/browser_monitor_reconnected_event.py
index a49ad351..39363367 100644
--- a/src/kernel/types/browsers/browser_monitor_reconnected_event.py
+++ b/src/kernel/types/browsers/browser_monitor_reconnected_event.py
@@ -19,6 +19,8 @@ class BrowserMonitorReconnectedEvent(BaseModel):
The CDP connection to Chrome was successfully re-established after a disconnection. Events emitted during the gap are lost. Computed state is reset, so navigation and network tracking restart fresh from this point.
"""
+ category: Literal["system"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_monitor_screenshot_event.py b/src/kernel/types/browsers/browser_monitor_screenshot_event.py
index 9b446fa9..bd2dc65b 100644
--- a/src/kernel/types/browsers/browser_monitor_screenshot_event.py
+++ b/src/kernel/types/browsers/browser_monitor_screenshot_event.py
@@ -17,6 +17,8 @@ class Data(BaseModel):
class BrowserMonitorScreenshotEvent(BaseModel):
"""A periodic screenshot of the browser viewport."""
+ category: Literal["system"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_network_idle_event.py b/src/kernel/types/browsers/browser_network_idle_event.py
index 4b4fae6b..b1877115 100644
--- a/src/kernel/types/browsers/browser_network_idle_event.py
+++ b/src/kernel/types/browsers/browser_network_idle_event.py
@@ -15,6 +15,8 @@ class BrowserNetworkIdleEvent(BaseModel):
A browser network idle event emitted after a 500ms quiet period with no in-flight HTTP requests.
"""
+ category: Literal["network"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_network_loading_failed_event.py b/src/kernel/types/browsers/browser_network_loading_failed_event.py
index bf566a6b..ac6b7961 100644
--- a/src/kernel/types/browsers/browser_network_loading_failed_event.py
+++ b/src/kernel/types/browsers/browser_network_loading_failed_event.py
@@ -39,6 +39,8 @@ class BrowserNetworkLoadingFailedEvent(BaseModel):
If the request was already in flight when CDP attached (no prior network_request was emitted for it), url, frame_id, loader_id, and resource_type are absent; BrowserEventContext is partially populated in that case.
"""
+ category: Literal["network"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_network_request_event.py b/src/kernel/types/browsers/browser_network_request_event.py
index e1bd9428..efea950b 100644
--- a/src/kernel/types/browsers/browser_network_request_event.py
+++ b/src/kernel/types/browsers/browser_network_request_event.py
@@ -55,6 +55,8 @@ class Data(BrowserEventContext):
class BrowserNetworkRequestEvent(BaseModel):
"""A browser network request sent event."""
+ category: Literal["network"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_network_response_event.py b/src/kernel/types/browsers/browser_network_response_event.py
index 8a71d24a..b39fefb8 100644
--- a/src/kernel/types/browsers/browser_network_response_event.py
+++ b/src/kernel/types/browsers/browser_network_response_event.py
@@ -52,6 +52,8 @@ class BrowserNetworkResponseEvent(BaseModel):
Fired after the response body is fully received, not when headers arrive.
"""
+ category: Literal["network"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_page_dom_content_loaded_event.py b/src/kernel/types/browsers/browser_page_dom_content_loaded_event.py
index e917ca32..99393cce 100644
--- a/src/kernel/types/browsers/browser_page_dom_content_loaded_event.py
+++ b/src/kernel/types/browsers/browser_page_dom_content_loaded_event.py
@@ -26,6 +26,8 @@ class Data(BrowserEventContext):
class BrowserPageDomContentLoadedEvent(BaseModel):
"""A browser DOMContentLoaded event (CDP Page.domContentEventFired)."""
+ category: Literal["page"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_page_layout_settled_event.py b/src/kernel/types/browsers/browser_page_layout_settled_event.py
index 289b53a5..f0558f12 100644
--- a/src/kernel/types/browsers/browser_page_layout_settled_event.py
+++ b/src/kernel/types/browsers/browser_page_layout_settled_event.py
@@ -15,6 +15,8 @@ class BrowserPageLayoutSettledEvent(BaseModel):
A browser layout settled event emitted 1 second after page load with no intervening layout shifts, indicating visual stability. Each layout shift resets the 1-second timer.
"""
+ category: Literal["page"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_page_layout_shift_event.py b/src/kernel/types/browsers/browser_page_layout_shift_event.py
index 336bfce2..fb578ac8 100644
--- a/src/kernel/types/browsers/browser_page_layout_shift_event.py
+++ b/src/kernel/types/browsers/browser_page_layout_shift_event.py
@@ -50,6 +50,8 @@ class BrowserPageLayoutShiftEvent(BaseModel):
A browser cumulative layout shift (CLS) event from the Performance Timeline API.
"""
+ category: Literal["page"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_page_lcp_event.py b/src/kernel/types/browsers/browser_page_lcp_event.py
index 13b9c270..0bcbddaa 100644
--- a/src/kernel/types/browsers/browser_page_lcp_event.py
+++ b/src/kernel/types/browsers/browser_page_lcp_event.py
@@ -56,6 +56,8 @@ class BrowserPageLcpEvent(BaseModel):
A browser Largest Contentful Paint (LCP) event from the Performance Timeline API.
"""
+ category: Literal["page"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_page_load_event.py b/src/kernel/types/browsers/browser_page_load_event.py
index b4d85c8f..f27658f1 100644
--- a/src/kernel/types/browsers/browser_page_load_event.py
+++ b/src/kernel/types/browsers/browser_page_load_event.py
@@ -26,6 +26,8 @@ class Data(BrowserEventContext):
class BrowserPageLoadEvent(BaseModel):
"""A browser page load event (CDP Page.loadEventFired)."""
+ category: Literal["page"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_page_navigation_event.py b/src/kernel/types/browsers/browser_page_navigation_event.py
index f857398c..5835d6d4 100644
--- a/src/kernel/types/browsers/browser_page_navigation_event.py
+++ b/src/kernel/types/browsers/browser_page_navigation_event.py
@@ -41,6 +41,8 @@ class BrowserPageNavigationEvent(BaseModel):
Carries nav context fields inline but not nav_seq, as this event resets the navigation epoch.
"""
+ category: Literal["page"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_page_navigation_settled_event.py b/src/kernel/types/browsers/browser_page_navigation_settled_event.py
index b5227ff4..6e5d31c2 100644
--- a/src/kernel/types/browsers/browser_page_navigation_settled_event.py
+++ b/src/kernel/types/browsers/browser_page_navigation_settled_event.py
@@ -15,6 +15,8 @@ class BrowserPageNavigationSettledEvent(BaseModel):
Emitted when page_dom_content_loaded and page_layout_settled have both fired for the same navigation, indicating the page is loaded and visually stable. Independent of network_idle; a single pending request does not block it.
"""
+ category: Literal["page"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
diff --git a/src/kernel/types/browsers/browser_page_tab_opened_event.py b/src/kernel/types/browsers/browser_page_tab_opened_event.py
index 9831aee1..144be476 100644
--- a/src/kernel/types/browsers/browser_page_tab_opened_event.py
+++ b/src/kernel/types/browsers/browser_page_tab_opened_event.py
@@ -31,6 +31,8 @@ class BrowserPageTabOpenedEvent(BaseModel):
A new browser tab or target was opened (CDP Target.attachedToTarget for page targets). Fires before a CDP session is attached to the new target, so session_id, frame_id, loader_id, and nav_seq are absent; this event does not compose BrowserEventContext. Consumers reading context fields generically should treat it as a special case.
"""
+ category: Literal["page"]
+
source: BrowserEventSource
"""Provenance metadata identifying which producer emitted the event."""
From 7cbc848fe33394ee05f5eb96d62cdc8b5b9b9d9c Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 1 Jun 2026 14:20:33 +0000
Subject: [PATCH 04/10] fix(api): move batch + get_mouse_position into Browser
Computer Controls tag
---
.stats.yml | 4 ++--
src/kernel/resources/browsers/browsers.py | 6 ++++++
src/kernel/resources/browsers/computer.py | 4 ++++
3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index f41061ca..8ba534ce 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 117
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-4bada2a5bdbde93018e5a1b1e80e134acbc5509cfdea94db6e4c5b799eba7b82.yml
-openapi_spec_hash: e0d541d480f5663b1e6bd3bb19a0fe61
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7548abe9fea7553e12a128b31f7dc7fc33f2558a9f20d2eb33464db5f61ab3ea.yml
+openapi_spec_hash: 4b701cc4b33a2c944a5a9b63e9f364a2
config_hash: e0741f8035aea13f71e54e0fdb88eaa4
diff --git a/src/kernel/resources/browsers/browsers.py b/src/kernel/resources/browsers/browsers.py
index c020c288..801cd152 100644
--- a/src/kernel/resources/browsers/browsers.py
+++ b/src/kernel/resources/browsers/browsers.py
@@ -133,6 +133,7 @@ def logs(self) -> LogsResource:
@cached_property
def computer(self) -> ComputerResource:
+ """Control mouse, keyboard, and screen on the browser instance."""
return ComputerResource(self._client)
@cached_property
@@ -680,6 +681,7 @@ def logs(self) -> AsyncLogsResource:
@cached_property
def computer(self) -> AsyncComputerResource:
+ """Control mouse, keyboard, and screen on the browser instance."""
return AsyncComputerResource(self._client)
@cached_property
@@ -1250,6 +1252,7 @@ def logs(self) -> LogsResourceWithRawResponse:
@cached_property
def computer(self) -> ComputerResourceWithRawResponse:
+ """Control mouse, keyboard, and screen on the browser instance."""
return ComputerResourceWithRawResponse(self._browsers.computer)
@cached_property
@@ -1311,6 +1314,7 @@ def logs(self) -> AsyncLogsResourceWithRawResponse:
@cached_property
def computer(self) -> AsyncComputerResourceWithRawResponse:
+ """Control mouse, keyboard, and screen on the browser instance."""
return AsyncComputerResourceWithRawResponse(self._browsers.computer)
@cached_property
@@ -1372,6 +1376,7 @@ def logs(self) -> LogsResourceWithStreamingResponse:
@cached_property
def computer(self) -> ComputerResourceWithStreamingResponse:
+ """Control mouse, keyboard, and screen on the browser instance."""
return ComputerResourceWithStreamingResponse(self._browsers.computer)
@cached_property
@@ -1433,6 +1438,7 @@ def logs(self) -> AsyncLogsResourceWithStreamingResponse:
@cached_property
def computer(self) -> AsyncComputerResourceWithStreamingResponse:
+ """Control mouse, keyboard, and screen on the browser instance."""
return AsyncComputerResourceWithStreamingResponse(self._browsers.computer)
@cached_property
diff --git a/src/kernel/resources/browsers/computer.py b/src/kernel/resources/browsers/computer.py
index 54b638e5..d2b57304 100644
--- a/src/kernel/resources/browsers/computer.py
+++ b/src/kernel/resources/browsers/computer.py
@@ -46,6 +46,8 @@
class ComputerResource(SyncAPIResource):
+ """Control mouse, keyboard, and screen on the browser instance."""
+
@cached_property
def with_raw_response(self) -> ComputerResourceWithRawResponse:
"""
@@ -649,6 +651,8 @@ def write_clipboard(
class AsyncComputerResource(AsyncAPIResource):
+ """Control mouse, keyboard, and screen on the browser instance."""
+
@cached_property
def with_raw_response(self) -> AsyncComputerResourceWithRawResponse:
"""
From 768e4e5709d46aff34bcec923b95f10d318640eb Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 1 Jun 2026 15:53:42 +0000
Subject: [PATCH 05/10] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 8ba534ce..e31b9566 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 117
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7548abe9fea7553e12a128b31f7dc7fc33f2558a9f20d2eb33464db5f61ab3ea.yml
-openapi_spec_hash: 4b701cc4b33a2c944a5a9b63e9f364a2
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-501a71a04e6a68427e378df10c7327025e3cb177f4550459b5a6eb752a177a25.yml
+openapi_spec_hash: d38661081dd50fded2208424bb19157b
config_hash: e0741f8035aea13f71e54e0fdb88eaa4
From 79a178a7d9e9e0867a5d38b2675d3e6088bab54e Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 2 Jun 2026 15:22:06 +0000
Subject: [PATCH 06/10] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index e31b9566..8fee23fa 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 117
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-501a71a04e6a68427e378df10c7327025e3cb177f4550459b5a6eb752a177a25.yml
-openapi_spec_hash: d38661081dd50fded2208424bb19157b
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7988523e72ff96a93d2913e63ba27c5bb94af9893b94fceeeda64e0b43fb0663.yml
+openapi_spec_hash: ce2ae9f9137d4c2bf947d446d00ebec8
config_hash: e0741f8035aea13f71e54e0fdb88eaa4
From 6e56cf2adecc945c972ce558009173ef0fd1d07e Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 2 Jun 2026 21:01:42 +0000
Subject: [PATCH 07/10] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 8fee23fa..0dd6d527 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 117
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-7988523e72ff96a93d2913e63ba27c5bb94af9893b94fceeeda64e0b43fb0663.yml
-openapi_spec_hash: ce2ae9f9137d4c2bf947d446d00ebec8
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-c8f49d6ea6355b703fa0e6cce4277df8954b9730ce4cdd3af5900f37769b40d9.yml
+openapi_spec_hash: ca03a797fb8e4cc79b6be4513f2fc6e7
config_hash: e0741f8035aea13f71e54e0fdb88eaa4
From efb45d6ca6dba4259348475cf0d418225930d570 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 3 Jun 2026 13:40:09 +0000
Subject: [PATCH 08/10] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 0dd6d527..a84f620b 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 117
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-c8f49d6ea6355b703fa0e6cce4277df8954b9730ce4cdd3af5900f37769b40d9.yml
-openapi_spec_hash: ca03a797fb8e4cc79b6be4513f2fc6e7
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a42305a37f0b2f42afb552acc9a5294c210a5278eb6067df803abe36da45c5b9.yml
+openapi_spec_hash: 4140db7dd999fee4b02e76dfb7d003b5
config_hash: e0741f8035aea13f71e54e0fdb88eaa4
From 5de851a5ff708a3e42e276e3cf9e2fe7ef0f2ed6 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 3 Jun 2026 15:29:18 +0000
Subject: [PATCH 09/10] feat(api): move browser telemetry SSE stream to
/browsers/{id}/telemetry/stream
---
.stats.yml | 6 +++---
api.md | 2 +-
src/kernel/resources/browsers/telemetry.py | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index a84f620b..5a5e5632 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 117
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a42305a37f0b2f42afb552acc9a5294c210a5278eb6067df803abe36da45c5b9.yml
-openapi_spec_hash: 4140db7dd999fee4b02e76dfb7d003b5
-config_hash: e0741f8035aea13f71e54e0fdb88eaa4
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-1acd8f0b76ab00e36b53cc3ca90b72b2199f3388b3e307890adb464b87f9a2d8.yml
+openapi_spec_hash: 82003125c1c2c5d82d19270bafb4a6ca
+config_hash: ede72e4ae65cc5a6d6927938b3455c46
diff --git a/api.md b/api.md
index c9e1b290..a7fda470 100644
--- a/api.md
+++ b/api.md
@@ -143,7 +143,7 @@ from kernel.types.browsers import (
Methods:
-- client.browsers.telemetry.stream(id) -> TelemetryStreamResponse
+- client.browsers.telemetry.stream(id) -> TelemetryStreamResponse
## Replays
diff --git a/src/kernel/resources/browsers/telemetry.py b/src/kernel/resources/browsers/telemetry.py
index cb95b2d1..008b1d29 100644
--- a/src/kernel/resources/browsers/telemetry.py
+++ b/src/kernel/resources/browsers/telemetry.py
@@ -80,7 +80,7 @@ def stream(
extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
extra_headers = {**strip_not_given({"Last-Event-ID": last_event_id}), **(extra_headers or {})}
return self._get(
- path_template("/browsers/{id}/telemetry", id=id),
+ path_template("/browsers/{id}/telemetry/stream", id=id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -149,7 +149,7 @@ async def stream(
extra_headers = {"Accept": "text/event-stream", **(extra_headers or {})}
extra_headers = {**strip_not_given({"Last-Event-ID": last_event_id}), **(extra_headers or {})}
return await self._get(
- path_template("/browsers/{id}/telemetry", id=id),
+ path_template("/browsers/{id}/telemetry/stream", id=id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
From f3de3710f8ad911487b84bffa97644b826f0d9e4 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 3 Jun 2026 15:29:50 +0000
Subject: [PATCH 10/10] release: 0.59.0
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 15 +++++++++++++++
pyproject.toml | 2 +-
src/kernel/_version.py | 2 +-
4 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 2fbefb94..85c31182 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.58.0"
+ ".": "0.59.0"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ba1969b1..1da0039a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,20 @@
# Changelog
+## 0.59.0 (2026-06-03)
+
+Full Changelog: [v0.58.0...v0.59.0](https://github.com/kernel/kernel-python-sdk/compare/v0.58.0...v0.59.0)
+
+### Features
+
+* api: surface category field on browser telemetry events ([06a2f7b](https://github.com/kernel/kernel-python-sdk/commit/06a2f7babbc8f6ea31e46f3dfeb8d09dbaae88f0))
+* **api:** move browser telemetry SSE stream to /browsers/{id}/telemetry/stream ([5de851a](https://github.com/kernel/kernel-python-sdk/commit/5de851a5ff708a3e42e276e3cf9e2fe7ef0f2ed6))
+* Support Byteful mobile proxies ([8c0ce1c](https://github.com/kernel/kernel-python-sdk/commit/8c0ce1c1533a538483419f4da0937a6153eb5273))
+
+
+### Bug Fixes
+
+* **api:** move batch + get_mouse_position into Browser Computer Controls tag ([7cbc848](https://github.com/kernel/kernel-python-sdk/commit/7cbc848fe33394ee05f5eb96d62cdc8b5b9b9d9c))
+
## 0.58.0 (2026-05-27)
Full Changelog: [v0.57.0...v0.58.0](https://github.com/kernel/kernel-python-sdk/compare/v0.57.0...v0.58.0)
diff --git a/pyproject.toml b/pyproject.toml
index 3ff0ba88..24264fbc 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "kernel"
-version = "0.58.0"
+version = "0.59.0"
description = "The official Python library for the kernel API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/kernel/_version.py b/src/kernel/_version.py
index 9422de86..86fdb652 100644
--- a/src/kernel/_version.py
+++ b/src/kernel/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "kernel"
-__version__ = "0.58.0" # x-release-please-version
+__version__ = "0.59.0" # x-release-please-version