Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions docs/src/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@
"sdk-reference/remotesession/observe",
"sdk-reference/remotesession/execute",
"sdk-reference/remotesession/scrape",
"sdk-reference/remotesession/fetch",
"sdk-reference/remotesession/replay",
"sdk-reference/remotesession/cdp_url",
"sdk-reference/remotesession/set_cookies",
Expand Down
20 changes: 20 additions & 0 deletions docs/src/features/sessions/browser-controls.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import Click from "/snippets/browser-controls/click.mdx";
import Fill from "/snippets/browser-controls/fill.mdx";
import Check from "/snippets/browser-controls/check.mdx";
import EvaluateJs from "/snippets/browser-controls/eval_js.mdx";
import Fetch from "/snippets/browser-controls/fetch.mdx";
import SelectDropdownOption from "/snippets/browser-controls/select_dropdown_option.mdx";
import PressKey from "/snippets/browser-controls/press_key.mdx";
import ScrollUp from "/snippets/browser-controls/scroll_up.mdx";
Expand Down Expand Up @@ -205,6 +206,25 @@ Evaluate JavaScript code on the current page and return the result. `session.eva

---

### Fetch

Issue an HTTP request from the page the session is on. `session.fetch(url)` runs the browser's own `fetch()` inside the current page, so the request carries the page's cookies, the session's proxy and the browser's network fingerprint. A relative URL resolves against the current page, which also keeps it same-origin; a cross-origin URL is subject to CORS as in any browser tab, so `goto` the target origin first. The response is shaped like `requests`: `status_code`, `ok`, `headers`, `text`, `url`, `json()` and `raise_for_status()`.

<Fetch />

**Parameters:**
- `url` (str): The URL to request, absolute or relative to the current page
- `method` (str): HTTP method, `GET` by default
- `headers` (dict): Extra request headers
- `params` (dict): Query parameters appended to the URL
- `json` (Any): Body serialised as JSON with an `application/json` content type
- `data` (str | dict): Body sent verbatim, or form-encoded when a dict
- `timeout` (float): Seconds before the request is aborted

**Use for:** Calling a site's own JSON endpoints with the session's cookies and IP, without leaving the browser

---

## Scrolling Actions

### ScrollUp
Expand Down
1 change: 1 addition & 0 deletions docs/src/llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ The SDK docs below are for generated-code editing and reference. They are not th
- [observe](https://docs.notte.cc/sdk-reference/remotesession/observe.md): Observes the current session page
- [execute](https://docs.notte.cc/sdk-reference/remotesession/execute.md): Executes an action on the current session page
- [scrape](https://docs.notte.cc/sdk-reference/remotesession/scrape.md): Scrape the current page data
- [fetch](https://docs.notte.cc/sdk-reference/remotesession/fetch.md): Issue an HTTP request from the page the session is on and return the response
- [replay](https://docs.notte.cc/sdk-reference/remotesession/replay.md): Get presigned URLs for the session replay
- [cdp_url](https://docs.notte.cc/sdk-reference/remotesession/cdp_url.md): Get the Chrome DevTools Protocol WebSocket URL for the session
- [set_cookies](https://docs.notte.cc/sdk-reference/remotesession/set_cookies.md): Uploads cookies to the session
Expand Down
51 changes: 51 additions & 0 deletions docs/src/sdk-reference/misc/fetchresponse.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
title: "FetchResponse"
description: "The response of a fetch call, with the shape of a requests response"
---



A non-2xx status is a response, not an error; call `raise_for_status()`
for the `requests` behaviour. `url` is the final URL after redirects

## Methods

### from_evaluated

```python
from_evaluated(raw: str) -> FetchResponse
```

Read the envelope `build_fetch_script` returns from the evaluated string

**Returns:**

<Visibility for="humans">[`FetchResponse`](/sdk-reference/misc/fetchresponse)</Visibility><Visibility for="agents">[`FetchResponse`](/sdk-reference/misc/fetchresponse.md)</Visibility>

---

### json

```python
json() -> Any
```

**Returns:**

`Any`

---

### raise_for_status

```python
raise_for_status() -> None
```

---



## Module

`notte_core.data.fetch`
14 changes: 14 additions & 0 deletions docs/src/sdk-reference/misc/remotesession.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,20 @@ Result containing execution details, any errors, and the updated session state.

---

### fetch

```python
fetch(url: <class 'str'>, method: <class 'str'> = GET, headers: collections.abc.Mapping[str, str] | None = None, params: collections.abc.Mapping[str, typing.Any] | None = None, json: typing.Any = None, data: str | collections.abc.Mapping[str, typing.Any] | None = None, timeout: float | None = None) -> <class 'notte_core.data.fetch.FetchResponse'>
```

Issue an HTTP request from the page the session is on and return the response

**Returns:**

<Visibility for="humans">[`FetchResponse`](/sdk-reference/misc/fetchresponse)</Visibility><Visibility for="agents">[`FetchResponse`](/sdk-reference/misc/fetchresponse.md)</Visibility>

---

### get_cookies

```python
Expand Down
52 changes: 52 additions & 0 deletions docs/src/sdk-reference/remotesession/fetch.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
title: "fetch"
description: "Issue an HTTP request from the page the session is on and return the response"
---
import AgentMdNotice from '/partials/agent-md-notice.mdx';

<AgentMdNotice />

The request runs inside the browser through `fetch()`, so it carries the
page's cookies, the session's proxy and the browser's own network
fingerprint. A relative `url` resolves against the current page, which
also makes it same-origin; a cross-origin URL is subject to CORS exactly
as in a browser tab, so `goto` the target origin first. Redirects are
followed and the final URL is on `response.url`. A non-2xx status is
returned, not raised; call `response.raise_for_status()` for the
`requests` behaviour. A network failure surfaces as the JavaScript error.

`json` is serialised as the body with an `application/json` content type,
`data` as a form body when it is a mapping or verbatim when it is a string.

```python
session.execute(type="goto", url="https://en.wikipedia.org/wiki/Main_Page")
summary = session.fetch("/api/rest_v1/page/summary/Main_Page").json()
```


## Parameters

<ParamField path="url" type="str" required>
</ParamField>

<ParamField path="method" type="str" default="GET">
</ParamField>

<ParamField path="headers" type="UnionType[Mapping[str, str], None]" default="None">
</ParamField>

<ParamField path="params" type="UnionType[Mapping[str, Any], None]" default="None">
</ParamField>

<ParamField path="json" type="Any" default="None">
</ParamField>

<ParamField path="data" type="UnionType[str, Mapping[str, Any], None]" default="None">
</ParamField>

<ParamField path="timeout" type="UnionType[float, None]" default="None">
</ParamField>

## Returns

<Visibility for="humans">[`FetchResponse`](/sdk-reference/misc/fetchresponse)</Visibility><Visibility for="agents">[`FetchResponse`](/sdk-reference/misc/fetchresponse.md)</Visibility>
18 changes: 18 additions & 0 deletions docs/src/sdk-reference/remotesession/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,24 @@ Attributes:
Executes an action on the current session page
</Card>
</Visibility>
<Visibility for="humans">
<Card
title="fetch"
icon="function"
href="/sdk-reference/remotesession/fetch"
>
Issue an HTTP request from the page the session is on and return the response
</Card>
</Visibility>
<Visibility for="agents">
<Card
title="fetch"
icon="function"
href="/sdk-reference/remotesession/fetch.md"
>
Issue an HTTP request from the page the session is on and return the response
</Card>
</Visibility>
<Visibility for="humans">
<Card
title="get_cookies"
Expand Down
15 changes: 15 additions & 0 deletions docs/src/snippets/browser-controls/fetch.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{/* Auto-generated mdx file. Do not edit! */}
{/* @sniptest testers/browser-controls/fetch.py */}

```python fetch.py
from notte_sdk import NotteClient

client = NotteClient()

with client.Session() as session:
session.execute(type="goto", url="https://en.wikipedia.org/wiki/Main_Page")
# fetch runs inside the page: same cookies, proxy and fingerprint as the browser
response = session.fetch("/api/rest_v1/page/summary/Main_Page")
response.raise_for_status()
summary = response.json()
```
11 changes: 11 additions & 0 deletions docs/src/testers/browser-controls/fetch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# @sniptest filename=fetch.py
from notte_sdk import NotteClient

client = NotteClient()

with client.Session() as session:
session.execute(type="goto", url="https://en.wikipedia.org/wiki/Main_Page")
# fetch runs inside the page: same cookies, proxy and fingerprint as the browser
response = session.fetch("/api/rest_v1/page/summary/Main_Page")
response.raise_for_status()
summary = response.json()
52 changes: 51 additions & 1 deletion packages/notte-browser/src/notte_browser/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import datetime as dt
import json
import re
from collections.abc import Sequence
from collections.abc import Mapping, Sequence
from pathlib import Path
from typing import Any, ClassVar, Literal, Unpack, overload

Expand Down Expand Up @@ -63,6 +63,7 @@
from notte_core.common.resource import AsyncResource, SyncResource
from notte_core.common.telemetry import track_usage
from notte_core.credentials.base import BaseVault, LocatorAttributes
from notte_core.data.fetch import FetchData, FetchResponse, build_fetch_script
from notte_core.data.space import DataSpace, ImageData, StructuredData, TBaseModel
from notte_core.errors.actions import ActionExecutionError, EvaluateJsNoDataError, InvalidActionError
from notte_core.errors.base import NotteBaseError
Expand Down Expand Up @@ -1085,6 +1086,55 @@ def evaluate_js(self, code: str, *, raise_on_failure: bool = True) -> str | Exec
"""
return asyncio.run(self.aevaluate_js(code, raise_on_failure=raise_on_failure))

async def afetch(
self,
url: str,
*,
method: str = "GET",
headers: Mapping[str, str] | None = None,
params: Mapping[str, Any] | None = None,
json: Any = None,
data: FetchData | None = None,
timeout: float | None = None,
) -> FetchResponse:
"""
Issue an HTTP request from the page the session is on and return the response.

The request runs inside the browser through `fetch()`, so it carries the
page's cookies, the session's proxy and the browser's own network
fingerprint. A relative `url` resolves against the current page, which
also makes it same-origin; a cross-origin URL is subject to CORS exactly
as in a browser tab, so `goto` the target origin first. Redirects are
followed and the final URL is on `response.url`. A non-2xx status is
returned, not raised; call `response.raise_for_status()` for the
`requests` behaviour. A network failure surfaces as the JavaScript error.

`json` is serialised as the body with an `application/json` content type,
`data` as a form body when it is a mapping or verbatim when it is a string.
"""
script = build_fetch_script(
url, method=method, headers=headers, params=params, json_body=json, data=data, timeout=timeout
)
return FetchResponse.from_evaluated(await self.aevaluate_js(script))

def fetch(
self,
url: str,
*,
method: str = "GET",
headers: Mapping[str, str] | None = None,
params: Mapping[str, Any] | None = None,
json: Any = None,
data: FetchData | None = None,
timeout: float | None = None,
) -> FetchResponse:
"""
Synchronous version of afetch.
"""
return asyncio.run(
self.afetch(url, method=method, headers=headers, params=params, json=json, data=data, timeout=timeout)
)

@overload
async def ascrape(self, /, *, only_images: Literal[True], raise_on_failure: bool = True) -> list[ImageData]: ...

Expand Down
Loading
Loading