hyperbrowser 0.29.0__py3-none-any.whl → 0.31.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of hyperbrowser might be problematic. Click here for more details.

@@ -6,6 +6,7 @@ from .managers.async_manager.session import SessionManager
6
6
  from .managers.async_manager.scrape import ScrapeManager
7
7
  from .managers.async_manager.crawl import CrawlManager
8
8
  from .managers.async_manager.extension import ExtensionManager
9
+ from .managers.async_manager.beta import Beta
9
10
  from .base import HyperbrowserBase
10
11
  from ..transport.async_transport import AsyncTransport
11
12
  from ..config import ClientConfig
@@ -29,6 +30,7 @@ class AsyncHyperbrowser(HyperbrowserBase):
29
30
  self.extract = ExtractManager(self)
30
31
  self.profiles = ProfileManager(self)
31
32
  self.extensions = ExtensionManager(self)
33
+ self.beta = Beta(self)
32
34
 
33
35
  async def close(self) -> None:
34
36
  await self.transport.close()
@@ -0,0 +1,6 @@
1
+ from .agents import Agents
2
+
3
+
4
+ class Beta:
5
+ def __init__(self, client):
6
+ self.agents = Agents(client)
@@ -0,0 +1,5 @@
1
+ class Agents:
2
+ def __init__(self, client):
3
+ from .browser_use import BrowserUseManager
4
+
5
+ self.browser_use = BrowserUseManager(client)
@@ -0,0 +1,69 @@
1
+ import asyncio
2
+ from hyperbrowser.exceptions import HyperbrowserError
3
+ from ......models import (
4
+ POLLING_ATTEMPTS,
5
+ BasicResponse,
6
+ StartBrowserUseTaskParams,
7
+ StartBrowserUseTaskResponse,
8
+ BrowserUseTaskStatusResponse,
9
+ BrowserUseTaskResponse,
10
+ )
11
+
12
+
13
+ class BrowserUseManager:
14
+ def __init__(self, client):
15
+ self._client = client
16
+
17
+ async def start(
18
+ self, params: StartBrowserUseTaskParams
19
+ ) -> StartBrowserUseTaskResponse:
20
+ response = await self._client.transport.post(
21
+ self._client._build_url("/task/browser-use"),
22
+ data=params.model_dump(exclude_none=True, by_alias=True),
23
+ )
24
+ return StartBrowserUseTaskResponse(**response.data)
25
+
26
+ async def get(self, job_id: str) -> BrowserUseTaskResponse:
27
+ response = await self._client.transport.get(
28
+ self._client._build_url(f"/task/browser-use/{job_id}")
29
+ )
30
+ return BrowserUseTaskResponse(**response.data)
31
+
32
+ async def get_status(self, job_id: str) -> BrowserUseTaskStatusResponse:
33
+ response = await self._client.transport.get(
34
+ self._client._build_url(f"/task/browser-use/{job_id}/status")
35
+ )
36
+ return BrowserUseTaskStatusResponse(**response.data)
37
+
38
+ async def stop(self, job_id: str) -> BasicResponse:
39
+ response = await self._client.transport.put(
40
+ self._client._build_url(f"/task/browser-use/{job_id}/stop")
41
+ )
42
+ return BasicResponse(**response.data)
43
+
44
+ async def start_and_wait(
45
+ self, params: StartBrowserUseTaskParams
46
+ ) -> BrowserUseTaskResponse:
47
+ job_start_resp = await self.start(params)
48
+ job_id = job_start_resp.job_id
49
+ if not job_id:
50
+ raise HyperbrowserError("Failed to start browser-use task job")
51
+
52
+ failures = 0
53
+ while True:
54
+ try:
55
+ job_response = await self.get_status(job_id)
56
+ if (
57
+ job_response.status == "completed"
58
+ or job_response.status == "failed"
59
+ or job_response.status == "stopped"
60
+ ):
61
+ return await self.get(job_id)
62
+ failures = 0
63
+ except Exception as e:
64
+ failures += 1
65
+ if failures >= POLLING_ATTEMPTS:
66
+ raise HyperbrowserError(
67
+ f"Failed to poll browser-use task job {job_id} after {POLLING_ATTEMPTS} attempts: {e}"
68
+ )
69
+ await asyncio.sleep(2)
@@ -2,6 +2,7 @@ from typing import List
2
2
  from ....models.session import (
3
3
  BasicResponse,
4
4
  CreateSessionParams,
5
+ GetSessionDownloadsUrlResponse,
5
6
  GetSessionRecordingUrlResponse,
6
7
  SessionDetail,
7
8
  SessionListParams,
@@ -47,7 +48,7 @@ class SessionManager:
47
48
 
48
49
  async def get_recording(self, id: str) -> List[SessionRecording]:
49
50
  response = await self._client.transport.get(
50
- self._client._build_url(f"/session/{id}/recording")
51
+ self._client._build_url(f"/session/{id}/recording"), None, True
51
52
  )
52
53
  return [SessionRecording(**recording) for recording in response.data]
53
54
 
@@ -56,3 +57,9 @@ class SessionManager:
56
57
  self._client._build_url(f"/session/{id}/recording-url")
57
58
  )
58
59
  return GetSessionRecordingUrlResponse(**response.data)
60
+
61
+ async def get_downloads_url(self, id: str) -> GetSessionDownloadsUrlResponse:
62
+ response = await self._client.transport.get(
63
+ self._client._build_url(f"/session/{id}/downloads-url")
64
+ )
65
+ return GetSessionDownloadsUrlResponse(**response.data)
@@ -0,0 +1,6 @@
1
+ from .agents import Agents
2
+
3
+
4
+ class Beta:
5
+ def __init__(self, client):
6
+ self.agents = Agents(client)
@@ -0,0 +1,5 @@
1
+ class Agents:
2
+ def __init__(self, client):
3
+ from .browser_use import BrowserUseManager
4
+
5
+ self.browser_use = BrowserUseManager(client)
@@ -0,0 +1,67 @@
1
+ import time
2
+ from hyperbrowser.exceptions import HyperbrowserError
3
+ from ......models import (
4
+ POLLING_ATTEMPTS,
5
+ BasicResponse,
6
+ StartBrowserUseTaskParams,
7
+ StartBrowserUseTaskResponse,
8
+ BrowserUseTaskStatusResponse,
9
+ BrowserUseTaskResponse,
10
+ )
11
+
12
+
13
+ class BrowserUseManager:
14
+ def __init__(self, client):
15
+ self._client = client
16
+
17
+ def start(self, params: StartBrowserUseTaskParams) -> StartBrowserUseTaskResponse:
18
+ response = self._client.transport.post(
19
+ self._client._build_url("/task/browser-use"),
20
+ data=params.model_dump(exclude_none=True, by_alias=True),
21
+ )
22
+ return StartBrowserUseTaskResponse(**response.data)
23
+
24
+ def get(self, job_id: str) -> BrowserUseTaskResponse:
25
+ response = self._client.transport.get(
26
+ self._client._build_url(f"/task/browser-use/{job_id}")
27
+ )
28
+ return BrowserUseTaskResponse(**response.data)
29
+
30
+ def get_status(self, job_id: str) -> BrowserUseTaskStatusResponse:
31
+ response = self._client.transport.get(
32
+ self._client._build_url(f"/task/browser-use/{job_id}/status")
33
+ )
34
+ return BrowserUseTaskStatusResponse(**response.data)
35
+
36
+ def stop(self, job_id: str) -> BasicResponse:
37
+ response = self._client.transport.put(
38
+ self._client._build_url(f"/task/browser-use/{job_id}/stop")
39
+ )
40
+ return BasicResponse(**response.data)
41
+
42
+ def start_and_wait(
43
+ self, params: StartBrowserUseTaskParams
44
+ ) -> BrowserUseTaskResponse:
45
+ job_start_resp = self.start(params)
46
+ job_id = job_start_resp.job_id
47
+ if not job_id:
48
+ raise HyperbrowserError("Failed to start browser-use task job")
49
+
50
+ failures = 0
51
+ while True:
52
+ try:
53
+ job_response = self.get_status(job_id)
54
+ if (
55
+ job_response.status == "completed"
56
+ or job_response.status == "failed"
57
+ or job_response.status == "stopped"
58
+ ):
59
+ return self.get(job_id)
60
+ failures = 0
61
+ except Exception as e:
62
+ failures += 1
63
+ if failures >= POLLING_ATTEMPTS:
64
+ raise HyperbrowserError(
65
+ f"Failed to poll browser-use task job {job_id} after {POLLING_ATTEMPTS} attempts: {e}"
66
+ )
67
+ time.sleep(2)
@@ -2,6 +2,7 @@ from typing import List
2
2
  from ....models.session import (
3
3
  BasicResponse,
4
4
  CreateSessionParams,
5
+ GetSessionDownloadsUrlResponse,
5
6
  GetSessionRecordingUrlResponse,
6
7
  SessionDetail,
7
8
  SessionListParams,
@@ -45,7 +46,7 @@ class SessionManager:
45
46
 
46
47
  def get_recording(self, id: str) -> List[SessionRecording]:
47
48
  response = self._client.transport.get(
48
- self._client._build_url(f"/session/{id}/recording")
49
+ self._client._build_url(f"/session/{id}/recording"), None, True
49
50
  )
50
51
  return [SessionRecording(**recording) for recording in response.data]
51
52
 
@@ -54,3 +55,9 @@ class SessionManager:
54
55
  self._client._build_url(f"/session/{id}/recording-url")
55
56
  )
56
57
  return GetSessionRecordingUrlResponse(**response.data)
58
+
59
+ def get_downloads_url(self, id: str) -> GetSessionDownloadsUrlResponse:
60
+ response = self._client.transport.get(
61
+ self._client._build_url(f"/session/{id}/downloads-url")
62
+ )
63
+ return GetSessionDownloadsUrlResponse(**response.data)
@@ -5,6 +5,7 @@ from .managers.sync_manager.profile import ProfileManager
5
5
  from .managers.sync_manager.session import SessionManager
6
6
  from .managers.sync_manager.scrape import ScrapeManager
7
7
  from .managers.sync_manager.crawl import CrawlManager
8
+ from .managers.sync_manager.beta import Beta
8
9
  from .managers.sync_manager.extension import ExtensionManager
9
10
  from .base import HyperbrowserBase
10
11
  from ..transport.sync import SyncTransport
@@ -29,6 +30,7 @@ class Hyperbrowser(HyperbrowserBase):
29
30
  self.extract = ExtractManager(self)
30
31
  self.profiles = ProfileManager(self)
31
32
  self.extensions = ExtensionManager(self)
33
+ self.beta = Beta(self)
32
34
 
33
35
  def close(self) -> None:
34
36
  self.transport.close()
hyperbrowser/config.py CHANGED
@@ -8,7 +8,7 @@ class ClientConfig:
8
8
  """Configuration for the Hyperbrowser client"""
9
9
 
10
10
  api_key: str
11
- base_url: str = "https://api.hyperbrowser.com"
11
+ base_url: str = "https://app.hyperbrowser.ai"
12
12
 
13
13
  @classmethod
14
14
  def from_env(cls) -> "ClientConfig":
@@ -17,6 +17,6 @@ class ClientConfig:
17
17
  raise ValueError("HYPERBROWSER_API_KEY environment variable is required")
18
18
 
19
19
  base_url = os.environ.get(
20
- "HYPERBROWSER_BASE_URL", "https://api.hyperbrowser.com"
20
+ "HYPERBROWSER_BASE_URL", "https://app.hyperbrowser.ai"
21
21
  )
22
22
  return cls(api_key=api_key, base_url=base_url)
@@ -0,0 +1,142 @@
1
+ from .consts import (
2
+ ScrapeFormat,
3
+ ScrapeWaitUntil,
4
+ ScrapePageStatus,
5
+ ScrapeScreenshotFormat,
6
+ RecordingStatus,
7
+ DownloadsStatus,
8
+ POLLING_ATTEMPTS,
9
+ Country,
10
+ OperatingSystem,
11
+ Platform,
12
+ ISO639_1,
13
+ State,
14
+ BrowserUseLlm,
15
+ )
16
+ from .crawl import (
17
+ CrawlJobStatus,
18
+ CrawlPageStatus,
19
+ StartCrawlJobParams,
20
+ StartCrawlJobResponse,
21
+ CrawledPage,
22
+ GetCrawlJobParams,
23
+ CrawlJobResponse,
24
+ )
25
+ from .extension import CreateExtensionParams, ExtensionResponse
26
+ from .extract import (
27
+ ExtractJobStatus,
28
+ StartExtractJobParams,
29
+ StartExtractJobResponse,
30
+ ExtractJobResponse,
31
+ )
32
+ from .profile import (
33
+ CreateProfileResponse,
34
+ ProfileResponse,
35
+ ProfileListParams,
36
+ ProfileListResponse,
37
+ )
38
+ from .scrape import (
39
+ ScrapeJobStatus,
40
+ ScreenshotOptions,
41
+ ScrapeOptions,
42
+ StartScrapeJobParams,
43
+ StartScrapeJobResponse,
44
+ ScrapeJobData,
45
+ ScrapeJobResponse,
46
+ StartBatchScrapeJobParams,
47
+ ScrapedPage,
48
+ GetBatchScrapeJobParams,
49
+ StartBatchScrapeJobResponse,
50
+ BatchScrapeJobResponse,
51
+ )
52
+ from .session import (
53
+ SessionStatus,
54
+ BasicResponse,
55
+ Session,
56
+ SessionDetail,
57
+ SessionListParams,
58
+ SessionListResponse,
59
+ ScreenConfig,
60
+ CreateSessionProfile,
61
+ CreateSessionParams,
62
+ SessionRecording,
63
+ GetSessionRecordingUrlResponse,
64
+ GetSessionDownloadsUrlResponse,
65
+ )
66
+ from .beta.agents.browser_use import (
67
+ StartBrowserUseTaskParams,
68
+ StartBrowserUseTaskResponse,
69
+ BrowserUseTaskStatusResponse,
70
+ BrowserUseTaskData,
71
+ BrowserUseTaskResponse,
72
+ )
73
+
74
+ __all__ = [
75
+ # consts
76
+ "BrowserUseLlm",
77
+ "ScrapeFormat",
78
+ "ScrapeWaitUntil",
79
+ "ScrapePageStatus",
80
+ "ScrapeScreenshotFormat",
81
+ "RecordingStatus",
82
+ "DownloadsStatus",
83
+ "POLLING_ATTEMPTS",
84
+ "Country",
85
+ "OperatingSystem",
86
+ "Platform",
87
+ "ISO639_1",
88
+ "State",
89
+ # crawl
90
+ "CrawlJobStatus",
91
+ "CrawlPageStatus",
92
+ "StartCrawlJobParams",
93
+ "StartCrawlJobResponse",
94
+ "CrawledPage",
95
+ "GetCrawlJobParams",
96
+ "CrawlJobResponse",
97
+ # extension
98
+ "CreateExtensionParams",
99
+ "ExtensionResponse",
100
+ # extract
101
+ "ExtractJobStatus",
102
+ "StartExtractJobParams",
103
+ "StartExtractJobResponse",
104
+ "ExtractJobResponse",
105
+ # profile
106
+ "CreateProfileResponse",
107
+ "ProfileResponse",
108
+ "ProfileListParams",
109
+ "ProfileListResponse",
110
+ # scrape
111
+ "ScrapeJobStatus",
112
+ "ScreenshotOptions",
113
+ "ScrapeOptions",
114
+ "StartScrapeJobParams",
115
+ "StartScrapeJobResponse",
116
+ "ScrapeJobData",
117
+ "ScrapeJobResponse",
118
+ "StartBatchScrapeJobParams",
119
+ "ScrapedPage",
120
+ "GetBatchScrapeJobParams",
121
+ "StartBatchScrapeJobResponse",
122
+ "BatchScrapeJobResponse",
123
+ # session
124
+ "SessionStatus",
125
+ "BasicResponse",
126
+ "Session",
127
+ "SessionDetail",
128
+ "SessionListParams",
129
+ "SessionListResponse",
130
+ "ScreenConfig",
131
+ "CreateSessionProfile",
132
+ "CreateSessionParams",
133
+ "SessionRecording",
134
+ "GetSessionRecordingUrlResponse",
135
+ "GetSessionDownloadsUrlResponse",
136
+ # agents
137
+ "StartBrowserUseTaskParams",
138
+ "StartBrowserUseTaskResponse",
139
+ "BrowserUseTaskStatusResponse",
140
+ "BrowserUseTaskData",
141
+ "BrowserUseTaskResponse",
142
+ ]
@@ -0,0 +1,177 @@
1
+ from typing import Literal, Optional, Union
2
+ from pydantic import BaseModel, ConfigDict, Field
3
+
4
+ from ...consts import BrowserUseLlm
5
+ from ...session import CreateSessionParams
6
+
7
+ BrowserUseTaskStatus = Literal["pending", "running", "completed", "failed", "stopped"]
8
+
9
+
10
+ class StartBrowserUseTaskParams(BaseModel):
11
+ """
12
+ Parameters for creating a new browser use task.
13
+ """
14
+
15
+ model_config = ConfigDict(
16
+ populate_by_alias=True,
17
+ )
18
+
19
+ task: str
20
+ llm: Optional[BrowserUseLlm] = Field(default=None, serialization_alias="llm")
21
+ session_id: Optional[str] = Field(default=None, serialization_alias="sessionId")
22
+ validate_output: Optional[bool] = Field(
23
+ default=None, serialization_alias="validateOutput"
24
+ )
25
+ use_vision: Optional[bool] = Field(default=None, serialization_alias="useVision")
26
+ use_vision_for_planner: Optional[bool] = Field(
27
+ default=None, serialization_alias="useVisionForPlanner"
28
+ )
29
+ max_actions_per_step: Optional[int] = Field(
30
+ default=None, serialization_alias="maxActionsPerStep"
31
+ )
32
+ max_input_tokens: Optional[int] = Field(
33
+ default=None, serialization_alias="maxInputTokens"
34
+ )
35
+ planner_llm: Optional[BrowserUseLlm] = Field(
36
+ default=None, serialization_alias="plannerLlm"
37
+ )
38
+ page_extraction_llm: Optional[BrowserUseLlm] = Field(
39
+ default=None, serialization_alias="pageExtractionLlm"
40
+ )
41
+ planner_interval: Optional[int] = Field(
42
+ default=None, serialization_alias="plannerInterval"
43
+ )
44
+ max_steps: Optional[int] = Field(default=None, serialization_alias="maxSteps")
45
+ keep_browser_open: Optional[bool] = Field(
46
+ default=None, serialization_alias="keepBrowserOpen"
47
+ )
48
+ session_options: Optional[CreateSessionParams] = Field(
49
+ default=None, serialization_alias="sessionOptions"
50
+ )
51
+
52
+
53
+ class StartBrowserUseTaskResponse(BaseModel):
54
+ """
55
+ Response from starting a browser use task.
56
+ """
57
+
58
+ model_config = ConfigDict(
59
+ populate_by_alias=True,
60
+ )
61
+
62
+ job_id: str = Field(alias="jobId")
63
+
64
+
65
+ class BrowserUseTaskStatusResponse(BaseModel):
66
+ """
67
+ Response from getting a browser use task status.
68
+ """
69
+
70
+ model_config = ConfigDict(
71
+ populate_by_alias=True,
72
+ )
73
+
74
+ status: BrowserUseTaskStatus
75
+
76
+
77
+ class BrowserUseAgentBrain(BaseModel):
78
+ evaluation_previous_goal: str
79
+ memory: str
80
+ next_goal: str
81
+
82
+
83
+ class BrowserUseAgentOutput(BaseModel):
84
+ current_state: BrowserUseAgentBrain
85
+ action: list[dict]
86
+
87
+
88
+ class BrowserUseActionResult(BaseModel):
89
+ is_done: Optional[bool] = False
90
+ success: Optional[bool] = None
91
+ extracted_content: Optional[str] = None
92
+ error: Optional[str] = None
93
+ include_in_memory: bool = False
94
+
95
+
96
+ class BrowserUseStepMetadata(BaseModel):
97
+ step_start_time: float
98
+ step_end_time: float
99
+ input_tokens: int
100
+ step_number: int
101
+
102
+
103
+ class BrowserUseTabInfo(BaseModel):
104
+ page_id: int
105
+ url: str
106
+ title: str
107
+
108
+
109
+ class BrowserUseCoordinates(BaseModel):
110
+ x: int
111
+ y: int
112
+
113
+
114
+ class BrowserUseCoordinateSet(BaseModel):
115
+ top_left: BrowserUseCoordinates
116
+ top_right: BrowserUseCoordinates
117
+ bottom_left: BrowserUseCoordinates
118
+ bottom_right: BrowserUseCoordinates
119
+ center: BrowserUseCoordinates
120
+ width: int
121
+ height: int
122
+
123
+
124
+ class BrowserUseViewportInfo(BaseModel):
125
+ scroll_x: int
126
+ scroll_y: int
127
+ width: int
128
+ height: int
129
+
130
+
131
+ class BrowserUseDOMHistoryElement(BaseModel):
132
+ tag_name: str
133
+ xpath: str
134
+ highlight_index: Optional[int]
135
+ entire_parent_branch_path: list[str]
136
+ attributes: dict[str, str]
137
+ shadow_root: bool = False
138
+ css_selector: Optional[str] = None
139
+ page_coordinates: Optional[BrowserUseCoordinateSet] = None
140
+ viewport_coordinates: Optional[BrowserUseCoordinateSet] = None
141
+ viewport_info: Optional[BrowserUseViewportInfo] = None
142
+
143
+
144
+ class BrowserUseBrowserStateHistory(BaseModel):
145
+ url: str
146
+ title: str
147
+ tabs: list[BrowserUseTabInfo]
148
+ interacted_element: Union[
149
+ list[Union[BrowserUseDOMHistoryElement, None]], list[None]
150
+ ]
151
+ screenshot: Optional[str] = None
152
+
153
+
154
+ class BrowserUseAgentHistory(BaseModel):
155
+ model_output: Union[BrowserUseAgentOutput, None]
156
+ result: list[BrowserUseActionResult]
157
+ state: BrowserUseBrowserStateHistory
158
+ metadata: Optional[BrowserUseStepMetadata] = None
159
+
160
+
161
+ class BrowserUseTaskData(BaseModel):
162
+ history: list[BrowserUseAgentHistory]
163
+
164
+
165
+ class BrowserUseTaskResponse(BaseModel):
166
+ """
167
+ Response from a browser use task.
168
+ """
169
+
170
+ model_config = ConfigDict(
171
+ populate_by_alias=True,
172
+ )
173
+
174
+ job_id: str = Field(alias="jobId")
175
+ status: BrowserUseTaskStatus
176
+ data: Optional[BrowserUseTaskData] = Field(default=None, alias="data")
177
+ error: Optional[str] = Field(default=None, alias="error")
@@ -4,9 +4,25 @@ ScrapeFormat = Literal["markdown", "html", "links", "screenshot"]
4
4
  ScrapeWaitUntil = Literal["load", "domcontentloaded", "networkidle"]
5
5
  ScrapePageStatus = Literal["completed", "failed", "pending", "running"]
6
6
  ScrapeScreenshotFormat = Literal["jpeg", "png", "webp"]
7
+ RecordingStatus = Literal[
8
+ "not_enabled", "pending", "in_progress", "completed", "failed"
9
+ ]
10
+ DownloadsStatus = Literal[
11
+ "not_enabled", "pending", "in_progress", "completed", "failed"
12
+ ]
7
13
 
8
14
  POLLING_ATTEMPTS = 5
9
15
 
16
+ BrowserUseLlm = Literal[
17
+ "gpt-4o",
18
+ "gpt-4o-mini",
19
+ "claude-3-7-sonnet-20250219",
20
+ "claude-3-5-haiku-20241022",
21
+ "gemini-2.0-flash",
22
+ "gemini-2.0-flash-thinking",
23
+ "gemini-2.0-pro",
24
+ ]
25
+
10
26
  Country = Literal[
11
27
  "AD",
12
28
  "AE",
@@ -55,4 +55,4 @@ class ExtractJobResponse(BaseModel):
55
55
  job_id: str = Field(alias="jobId")
56
56
  status: ExtractJobStatus
57
57
  error: Optional[str] = None
58
- data: Optional[Any] = None
58
+ data: Optional[dict] = None
@@ -6,8 +6,10 @@ from pydantic import BaseModel, ConfigDict, Field, field_validator
6
6
  from hyperbrowser.models.consts import (
7
7
  ISO639_1,
8
8
  Country,
9
+ DownloadsStatus,
9
10
  OperatingSystem,
10
11
  Platform,
12
+ RecordingStatus,
11
13
  State,
12
14
  )
13
15
 
@@ -144,7 +146,7 @@ class CreateSessionParams(BaseModel):
144
146
  default=None, serialization_alias="proxyServerUsername"
145
147
  )
146
148
  proxy_country: Optional[Country] = Field(
147
- default="US", serialization_alias="proxyCountry"
149
+ default=None, serialization_alias="proxyCountry"
148
150
  )
149
151
  proxy_state: Optional[State] = Field(default=None, serialization_alias="proxyState")
150
152
  proxy_city: Optional[str] = Field(default=None, serialization_alias="proxyCity")
@@ -176,6 +178,9 @@ class CreateSessionParams(BaseModel):
176
178
  browser_args: Optional[List[str]] = Field(
177
179
  default=None, serialization_alias="browserArgs"
178
180
  )
181
+ save_downloads: Optional[bool] = Field(
182
+ default=None, serialization_alias="saveDownloads"
183
+ )
179
184
 
180
185
 
181
186
  class SessionRecording(BaseModel):
@@ -202,4 +207,20 @@ class GetSessionRecordingUrlResponse(BaseModel):
202
207
  populate_by_alias=True,
203
208
  )
204
209
 
205
- recording_url: str = Field(alias="recordingUrl")
210
+ status: RecordingStatus = Field(alias="status")
211
+ recording_url: Optional[str] = Field(default=None, alias="recordingUrl")
212
+ error: Optional[str] = Field(default=None, alias="error")
213
+
214
+
215
+ class GetSessionDownloadsUrlResponse(BaseModel):
216
+ """
217
+ Response containing the signed URL for the session downloads.
218
+ """
219
+
220
+ model_config = ConfigDict(
221
+ populate_by_alias=True,
222
+ )
223
+
224
+ status: DownloadsStatus = Field(alias="status")
225
+ downloads_url: Optional[str] = Field(default=None, alias="downloadsUrl")
226
+ error: Optional[str] = Field(default=None, alias="error")
@@ -80,11 +80,15 @@ class AsyncTransport(TransportStrategy):
80
80
  except Exception as e:
81
81
  raise HyperbrowserError("Post request failed", original_error=e)
82
82
 
83
- async def get(self, url: str, params: Optional[dict] = None) -> APIResponse:
83
+ async def get(
84
+ self, url: str, params: Optional[dict] = None, follow_redirects: bool = False
85
+ ) -> APIResponse:
84
86
  if params:
85
87
  params = {k: v for k, v in params.items() if v is not None}
86
88
  try:
87
- response = await self.client.get(url, params=params)
89
+ response = await self.client.get(
90
+ url, params=params, follow_redirects=follow_redirects
91
+ )
88
92
  return await self._handle_response(response)
89
93
  except HyperbrowserError:
90
94
  raise
@@ -59,11 +59,15 @@ class SyncTransport(TransportStrategy):
59
59
  except Exception as e:
60
60
  raise HyperbrowserError("Post request failed", original_error=e)
61
61
 
62
- def get(self, url: str, params: Optional[dict] = None) -> APIResponse:
62
+ def get(
63
+ self, url: str, params: Optional[dict] = None, follow_redirects: bool = False
64
+ ) -> APIResponse:
63
65
  if params:
64
66
  params = {k: v for k, v in params.items() if v is not None}
65
67
  try:
66
- response = self.client.get(url, params=params)
68
+ response = self.client.get(
69
+ url, params=params, follow_redirects=follow_redirects
70
+ )
67
71
  return self._handle_response(response)
68
72
  except HyperbrowserError:
69
73
  raise
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: hyperbrowser
3
- Version: 0.29.0
3
+ Version: 0.31.0
4
4
  Summary: Python SDK for hyperbrowser
5
5
  License: MIT
6
6
  Author: Nikhil Shahi
@@ -1,36 +1,44 @@
1
1
  hyperbrowser/__init__.py,sha256=zWGcLhqhvWy6BTwuNpzWK1-0LpIn311ks-4U9nrsb7Y,187
2
- hyperbrowser/client/async_client.py,sha256=L7mbzg_wOVMneOm6-bA5XaBoVWUmybuRogE4YEMR5Bg,1389
2
+ hyperbrowser/client/async_client.py,sha256=CfANIK2rXVKPaxCTVtTxXvISrYeBFae6qMy_fUr7oZE,1466
3
3
  hyperbrowser/client/base.py,sha256=9gFma7RdvJBUlDCqr8tZd315UPrjn4ldU4B0-Y-L4O4,1268
4
+ hyperbrowser/client/managers/async_manager/beta/__init__.py,sha256=cRTeKvEogiUUK3WS02YKWM-sU6LCzXoALYclWgM0E_U,110
5
+ hyperbrowser/client/managers/async_manager/beta/agents/__init__.py,sha256=GVDrShmJtGJt2r2BxJ_aZiWLz3M5D54MJvOIgOhBPv4,151
6
+ hyperbrowser/client/managers/async_manager/beta/agents/browser_use.py,sha256=d1jEvkwOoNbAXDOv2IH7pdWrwGzSWrz3Us4skQM2Dew,2510
4
7
  hyperbrowser/client/managers/async_manager/crawl.py,sha256=n0KhHarVpPFwjjlc9UnhSfD5vvdC2kpcXHVr8vPiKxE,3870
5
8
  hyperbrowser/client/managers/async_manager/extension.py,sha256=a-xYtXXdCspukYtsguRgjEoQ8E_kzzA2tQAJtIyCtAs,1439
6
9
  hyperbrowser/client/managers/async_manager/extract.py,sha256=9p8dGLYmoow7smnQ0BTRN6diDmIayjW-EPRGzzvheZk,2102
7
10
  hyperbrowser/client/managers/async_manager/profile.py,sha256=f2uX2GGYdgL0fyzB0jnI-L-nWleqG6cwZ0pc1K1zdQY,1244
8
11
  hyperbrowser/client/managers/async_manager/scrape.py,sha256=Lr6oicTX3U1xooczUVQlsq2mzIhAKEW-A9909ZdSzKc,5720
9
- hyperbrowser/client/managers/async_manager/session.py,sha256=KN28FEwGdJ1GC0aq_4JFDsVQrWs7CigBAwgQE5BtaEE,2005
12
+ hyperbrowser/client/managers/async_manager/session.py,sha256=jO9Z2MSooG9eTmdsOWiNU0mFYdrxh5HirNnFqgwDIn0,2330
13
+ hyperbrowser/client/managers/sync_manager/beta/__init__.py,sha256=cRTeKvEogiUUK3WS02YKWM-sU6LCzXoALYclWgM0E_U,110
14
+ hyperbrowser/client/managers/sync_manager/beta/agents/__init__.py,sha256=GVDrShmJtGJt2r2BxJ_aZiWLz3M5D54MJvOIgOhBPv4,151
15
+ hyperbrowser/client/managers/sync_manager/beta/agents/browser_use.py,sha256=OSYDCO9huA90RMyZy28-_VOjeibBT0sHlbyf77FCTT4,2412
10
16
  hyperbrowser/client/managers/sync_manager/crawl.py,sha256=uAVmjhUbamVnzAAyfswq1bdBR5c7JrfGVvPdVmmw4R8,3799
11
17
  hyperbrowser/client/managers/sync_manager/extension.py,sha256=1YoyTZtMo43trl9jAsXv95aor0nBHiJEmLva39jFW-k,1415
12
18
  hyperbrowser/client/managers/sync_manager/extract.py,sha256=XocMKC0qAarRpE12KU4m_mi1KhUOHp3-TK4dLeiIn6E,2034
13
19
  hyperbrowser/client/managers/sync_manager/profile.py,sha256=va6mlhQ5SKZa-viEGFNzV6UBZEP5SqwVp32_oxC_NzM,1196
14
20
  hyperbrowser/client/managers/sync_manager/scrape.py,sha256=y4YB-NusXRi3brE7jBGRBHGANY-_-aHMBirKuuU6mdg,5579
15
- hyperbrowser/client/managers/sync_manager/session.py,sha256=x2yHIkamcIHbmzMLQtJHzY93UgAlhZ02gHMMmJqiHpc,1911
16
- hyperbrowser/client/sync.py,sha256=HgglJY9pNdW987OzNO_5dSZgj1AfAqovCmY99WYQD2E,1213
17
- hyperbrowser/config.py,sha256=2J6GYNR_83vzJZ6jEV-LXO1U-q6DHIrfyAU0WrUPhw8,625
21
+ hyperbrowser/client/managers/sync_manager/session.py,sha256=aE4T9LWbOKcKCnh04n3rwnjeyus73Z47otrdCGTTKSM,2224
22
+ hyperbrowser/client/sync.py,sha256=WK0KqoJb7ZHBVy50TYis7LENvA3KRQk45OzIZcxwWe8,1289
23
+ hyperbrowser/config.py,sha256=6xtUiVXy7MQMiARAsadP62U46tL0wzVMDuGmQBcH_LQ,623
18
24
  hyperbrowser/exceptions.py,sha256=SUUkptK2OL36xDORYmSicaTYR7pMbxeWAjAgz35xnM8,1171
19
- hyperbrowser/models/consts.py,sha256=sFdJ4fDIL5By7wSzh6As-jc3L3-Ul3XqZvvfS8D3J6U,6223
25
+ hyperbrowser/models/__init__.py,sha256=G6Fdm7UQ_3Sz85hRgklA76vwThbyDE47-lTthqHjb88,3195
26
+ hyperbrowser/models/beta/agents/browser_use.py,sha256=Yag3TyC8jJIpnVr280UVDtS-nW6_gqr5-1gBCdbVZ80,4771
27
+ hyperbrowser/models/consts.py,sha256=SP0RTMiusFURrEUBoyVgVOVKINk5paYoRpWHfLucwEA,6622
20
28
  hyperbrowser/models/crawl.py,sha256=22hP_DPZMfa2MAfOeJ90qj5CH4rr7VtQT1gCQqO8jO8,2610
21
29
  hyperbrowser/models/extension.py,sha256=nXjKXKt9R7RxyZ4hd3EvfqZsEGy_ufh1r5j2mqCLykQ,804
22
- hyperbrowser/models/extract.py,sha256=Thq1wQhXlS-dh4442JLDONGOYix06s3gjWSnP1OuyN4,1528
30
+ hyperbrowser/models/extract.py,sha256=kkcM7DXkwnFJ7d_JZMDAb4VAlQdh-snJktFpJs92z8U,1529
23
31
  hyperbrowser/models/profile.py,sha256=KRb_LNxxW00AsD_thzzthFS51vInJawt1RcoNz4Q9i8,1322
24
32
  hyperbrowser/models/scrape.py,sha256=ZdVNN4rh7EKLh-O1Ou5aU_OgTNxC9pFQlkG-Q2fR-Z4,4611
25
- hyperbrowser/models/session.py,sha256=IkkhwiTwH43IvrAa5Zqs3hVpF7pPz0ly3mN8P-4ZN3Y,6047
33
+ hyperbrowser/models/session.py,sha256=i1NkrQWNlKziDd98ySdrUUH7XSv6qOa2cmiK5vV7VeI,6730
26
34
  hyperbrowser/tools/__init__.py,sha256=OUaTUM-kiigYmzfbpx3XQhzMK1xT1wd8cqXgR4znsAY,2021
27
35
  hyperbrowser/tools/anthropic.py,sha256=5pEkJm1H-26GToTwXsDjo4GGqVy1hATws4Pg59mumow,1667
28
36
  hyperbrowser/tools/openai.py,sha256=4-71IIWSxc_ByhywcfWj9-QI9iYNEe0xO6B2spE8WG0,2200
29
37
  hyperbrowser/tools/schema.py,sha256=cR2MUX8TvUyN8TnCyeX0pccp4AmPjrdaKzuAXRThOJo,3075
30
- hyperbrowser/transport/async_transport.py,sha256=MIPJvilvZWBPXLZ96c9OohuN6TN9DaaU0EnyleG3q6g,4017
38
+ hyperbrowser/transport/async_transport.py,sha256=6HKoeM5TutIqraEscEWobvSPWF3iVKh2hPflGNKwykw,4128
31
39
  hyperbrowser/transport/base.py,sha256=ildpMrDiM8nvrSGrH2LTOafmB17T7PQB_NQ1ODA378U,1703
32
- hyperbrowser/transport/sync.py,sha256=ER844H_OCPCrnmbc58cuqphWTVvCZJQn7-D7ZenCr3Y,3311
33
- hyperbrowser-0.29.0.dist-info/LICENSE,sha256=6rUGKlyKb_1ZAH7h7YITYAAUNFN3MNGGKCyfrw49NLE,1071
34
- hyperbrowser-0.29.0.dist-info/METADATA,sha256=8UmTW7HXMy4-Z3j-tyPAkQLTSttXYwoaZjtix9ise5U,3438
35
- hyperbrowser-0.29.0.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
36
- hyperbrowser-0.29.0.dist-info/RECORD,,
40
+ hyperbrowser/transport/sync.py,sha256=aUVpxWF8sqSycLNKxVNEZvlsZSoqc1eHgPK1Y1QA1u8,3422
41
+ hyperbrowser-0.31.0.dist-info/LICENSE,sha256=6rUGKlyKb_1ZAH7h7YITYAAUNFN3MNGGKCyfrw49NLE,1071
42
+ hyperbrowser-0.31.0.dist-info/METADATA,sha256=U-knMKE23b211O_PuahtsmP2j94rXKaeeiXnwhjcB90,3438
43
+ hyperbrowser-0.31.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
44
+ hyperbrowser-0.31.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.0.1
2
+ Generator: poetry-core 2.1.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any