Skip to content

release: 1.5.0 #151

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "1.4.0"
".": "1.5.0"
}
2 changes: 1 addition & 1 deletion .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 18
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fbrowserbase-e2ed1b5267eeff92982918505349017b9155da2c7ab948787ab11cf9068af1b8.yml
openapi_spec_hash: 6639c21dccb52ca610cae833227a9791
config_hash: 74882e23a455dece33e43a27e67f0fbb
config_hash: b3ca4ec5b02e5333af51ebc2e9fdef1b
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Changelog

## 1.5.0 (2025-06-03)

Full Changelog: [v1.4.0...v1.5.0](https://github.com/browserbase/sdk-python/compare/v1.4.0...v1.5.0)

### Features

* **client:** add follow_redirects request option ([a8b0b5e](https://github.com/browserbase/sdk-python/commit/a8b0b5e4c6445e0e8c0d3673a090aabab09a50fd))


### Chores

* **docs:** grammar improvements ([f32a9e2](https://github.com/browserbase/sdk-python/commit/f32a9e258a9b0b4d29c24137d5a7207907f00f9b))
* **docs:** remove reference to rye shell ([07d129a](https://github.com/browserbase/sdk-python/commit/07d129a04211037d123b06d36347741960e75323))
* **docs:** remove unnecessary param examples ([62209dc](https://github.com/browserbase/sdk-python/commit/62209dcac034f40ac8b3b8a119e532201a227680))

## 1.4.0 (2025-05-16)

Full Changelog: [v1.3.0...v1.4.0](https://github.com/browserbase/sdk-python/compare/v1.3.0...v1.4.0)
Expand Down
3 changes: 1 addition & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ $ rye sync --all-features
You can then run scripts using `rye run python script.py` or by activating the virtual environment:

```sh
$ rye shell
# or manually activate - https://docs.python.org/3/library/venv.html#how-venvs-work
# Activate the virtual environment - https://docs.python.org/3/library/venv.html#how-venvs-work
$ source .venv/bin/activate

# now you can omit the `rye run` prefix
Expand Down
32 changes: 1 addition & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,37 +101,7 @@ client = Browserbase()

session = client.sessions.create(
project_id="projectId",
browser_settings={
"advanced_stealth": True,
"block_ads": True,
"captcha_image_selector": "captchaImageSelector",
"captcha_input_selector": "captchaInputSelector",
"context": {
"id": "id",
"persist": True,
},
"extension_id": "extensionId",
"fingerprint": {
"browsers": ["chrome"],
"devices": ["desktop"],
"http_version": "1",
"locales": ["string"],
"operating_systems": ["android"],
"screen": {
"max_height": 0,
"max_width": 0,
"min_height": 0,
"min_width": 0,
},
},
"log_session": True,
"record_session": True,
"solve_captchas": True,
"viewport": {
"height": 0,
"width": 0,
},
},
browser_settings={},
)
print(session.browser_settings)
```
Expand Down
4 changes: 2 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ before making any information public.
## Reporting Non-SDK Related Security Issues

If you encounter security issues that are not directly related to SDKs but pertain to the services
or products provided by Browserbase please follow the respective company's security reporting guidelines.
or products provided by Browserbase, please follow the respective company's security reporting guidelines.

### Browserbase Terms and Policies

Please contact [email protected] for any questions or concerns regarding security of our services.
Please contact [email protected] for any questions or concerns regarding the security of our services.

---

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "browserbase"
version = "1.4.0"
version = "1.5.0"
description = "The official Python library for the Browserbase API"
dynamic = ["readme"]
license = "Apache-2.0"
Expand Down
6 changes: 6 additions & 0 deletions src/browserbase/_base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,9 @@ def request(
if self.custom_auth is not None:
kwargs["auth"] = self.custom_auth

if options.follow_redirects is not None:
kwargs["follow_redirects"] = options.follow_redirects

log.debug("Sending HTTP Request: %s %s", request.method, request.url)

response = None
Expand Down Expand Up @@ -1460,6 +1463,9 @@ async def request(
if self.custom_auth is not None:
kwargs["auth"] = self.custom_auth

if options.follow_redirects is not None:
kwargs["follow_redirects"] = options.follow_redirects

log.debug("Sending HTTP Request: %s %s", request.method, request.url)

response = None
Expand Down
2 changes: 2 additions & 0 deletions src/browserbase/_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,7 @@ class FinalRequestOptionsInput(TypedDict, total=False):
idempotency_key: str
json_data: Body
extra_json: AnyMapping
follow_redirects: bool


@final
Expand All @@ -750,6 +751,7 @@ class FinalRequestOptions(pydantic.BaseModel):
files: Union[HttpxRequestFiles, None] = None
idempotency_key: Union[str, None] = None
post_parser: Union[Callable[[Any], Any], NotGiven] = NotGiven()
follow_redirects: Union[bool, None] = None

# It should be noted that we cannot use `json` here as that would override
# a BaseModel method in an incompatible fashion.
Expand Down
2 changes: 2 additions & 0 deletions src/browserbase/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ class RequestOptions(TypedDict, total=False):
params: Query
extra_json: AnyMapping
idempotency_key: str
follow_redirects: bool


# Sentinel class used until PEP 0661 is accepted
Expand Down Expand Up @@ -215,3 +216,4 @@ class _GenericAlias(Protocol):

class HttpxSendArgs(TypedDict, total=False):
auth: httpx.Auth
follow_redirects: bool
2 changes: 1 addition & 1 deletion src/browserbase/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

__title__ = "browserbase"
__version__ = "1.4.0" # x-release-please-version
__version__ = "1.5.0" # x-release-please-version
54 changes: 54 additions & 0 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,33 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:

assert response.http_request.headers.get("x-stainless-retry-count") == "42"

@pytest.mark.respx(base_url=base_url)
def test_follow_redirects(self, respx_mock: MockRouter) -> None:
# Test that the default follow_redirects=True allows following redirects
respx_mock.post("/redirect").mock(
return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"})
)
respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"}))

response = self.client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response)
assert response.status_code == 200
assert response.json() == {"status": "ok"}

@pytest.mark.respx(base_url=base_url)
def test_follow_redirects_disabled(self, respx_mock: MockRouter) -> None:
# Test that follow_redirects=False prevents following redirects
respx_mock.post("/redirect").mock(
return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"})
)

with pytest.raises(APIStatusError) as exc_info:
self.client.post(
"/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response
)

assert exc_info.value.response.status_code == 302
assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected"


class TestAsyncBrowserbase:
client = AsyncBrowserbase(base_url=base_url, api_key=api_key, _strict_response_validation=True)
Expand Down Expand Up @@ -1659,3 +1686,30 @@ async def test_main() -> None:
raise AssertionError("calling get_platform using asyncify resulted in a hung process")

time.sleep(0.1)

@pytest.mark.respx(base_url=base_url)
async def test_follow_redirects(self, respx_mock: MockRouter) -> None:
# Test that the default follow_redirects=True allows following redirects
respx_mock.post("/redirect").mock(
return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"})
)
respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"}))

response = await self.client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response)
assert response.status_code == 200
assert response.json() == {"status": "ok"}

@pytest.mark.respx(base_url=base_url)
async def test_follow_redirects_disabled(self, respx_mock: MockRouter) -> None:
# Test that follow_redirects=False prevents following redirects
respx_mock.post("/redirect").mock(
return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"})
)

with pytest.raises(APIStatusError) as exc_info:
await self.client.post(
"/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response
)

assert exc_info.value.response.status_code == 302
assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected"