pyodide.http#

The pyodide.http module provides HTTP client functionality specifically designed for browser and WebAssembly environments where traditional Python HTTP libraries (like urllib) face significant limitations.

Network Limitations in Pyodide#

Due to browser security constraints and WebAssembly’s sandboxed environment, standard Python networking libraries have several limitations:

  • No raw socket access: Browser security prevents direct socket operations

  • CORS restrictions: Cross-origin requests are limited by browser CORS policies

  • No synchronous networking in main thread: Traditional blocking HTTP calls can freeze the browser UI

  • Limited protocol support: Only HTTP/HTTPS protocols are available, no TCP/UDP sockets

HTTP Client Alternatives#

Pyodide provides two complementary HTTP client solutions:

pyfetch - Asynchronous HTTP Client#

Based on the browser’s native Fetch API, pyfetch provides:

  • Asynchronous operations: Non-blocking HTTP requests using async/await

  • Full browser integration: Leverages browser’s networking stack and security features

  • Modern API: Clean, Promise-based interface similar to JavaScript fetch()

# Asynchronous HTTP request
from pyodide.http import pyfetch
response = await pyfetch("https://api.example.com/data")
data = await response.json()

pyxhr - Synchronous HTTP Client#

Based on XMLHttpRequest, pyxhr provides:

  • Synchronous operations: Blocking HTTP requests for simpler code patterns

  • requests-like API: Familiar interface for Python developers

  • Browser compatibility: Works in all modern browsers supporting XMLHttpRequest

  • Lightweight: Minimal overhead for simple HTTP operations

# Synchronous HTTP request
from pyodide.http import pyxhr
response = pyxhr.get("https://api.example.com/data")
data = response.json()

Choosing Between pyfetch and pyxhr#

Use pyfetch when:

  • Working with async/await patterns

  • Need advanced features like streaming or request cancellation

  • Building responsive web applications that shouldn’t block the UI

  • Integrating with other asynchronous Python code

Use pyxhr when:

  • Prefer synchronous, blocking operations

  • Porting existing code that uses requests-like patterns

  • Need simple HTTP operations without async complexity

  • Working in environments where sync operations are acceptable

Exceptions:

AbortError(reason)

BodyUsedError(*args)

HttpStatusError(status, status_text, url)

A subclass of OSError raised by FetchResponse.raise_for_status() if the response status is 4XX or 5XX.

Classes:

FetchResponse(request, js_response[, ...])

A wrapper for a Javascript fetch Response.

Functions:

open_url(url)

Fetches a given URL synchronously.

pyfetch(request, /, *[, signal, fetcher])

Fetch the url and return the response.

exception pyodide.http.AbortError(reason)#
Parameters:

reason (JsException)

exception pyodide.http.BodyUsedError(*args)#
Parameters:

args (Any)

class pyodide.http.FetchResponse(request, js_response, abort_controller=None, abort_signal=None)#

A wrapper for a Javascript fetch Response.

Parameters:
abort(reason=None)#

Abort the fetch request.

In case abort_controller is not set, a ValueError is raised.

Parameters:

reason (Any)

Return type:

None

body_used: bool#

Has the response been used yet?

If so, attempting to retrieve the body again will raise an OSError. Use clone() first to avoid this. See Response.bodyUsed.

async buffer()#

Return the response body as a Javascript ArrayBuffer.

See Response.arrayBuffer().

Return type:

JsBuffer

async bytes()#

Return the response body as a bytes object

Return type:

bytes

clone()#

Return an identical copy of the FetchResponse.

This method exists to allow multiple uses of FetchResponse objects. See Response.clone().

Return type:

FetchResponse

headers: dict[str, str]#

Response headers as dictionary.

async json(**kwargs)#

Treat the response body as a JSON string and use json.loads() to parse it into a Python object.

Any keyword arguments are passed to json.loads().

Parameters:

kwargs (Any)

Return type:

Any

async memoryview()#

Return the response body as a memoryview object

Return type:

memoryview

ok: bool#

Was the request successful?

See Response.ok.

raise_for_status()#

Raise an HttpStatusError if the status of the response is an error (4xx or 5xx)

Return type:

None

redirected: bool#

Was the request redirected?

See Response.redirected.

status: int#

Response status code

See Response.status.

status_text: str#

Response status text

See Response.statusText.

async string()#

Return the response body as a string

Does the same thing as FetchResponse.text().

Return type:

str

Deprecated since version 0.24.0: Use FetchResponse.text() instead.

async text()#

Return the response body as a string

Return type:

str

type: str#

The type of the response.

See Response.type.

async unpack_archive(*, extract_dir=None, format=None)#

Treat the data as an archive and unpack it into target directory.

Assumes that the file is an archive in a format that shutil has an unpacker for. The arguments extract_dir and format are passed directly on to shutil.unpack_archive().

Parameters:
  • extract_dir (str | None) – Directory to extract the archive into. If not provided, the current working directory is used.

  • format (str | None) – The archive format: one of "zip", "tar", "gztar", "bztar". Or any other format registered with shutil.register_unpack_format(). If not provided, unpack_archive() will use the archive file name extension and see if an unpacker was registered for that extension. In case none is found, a ValueError is raised.

Return type:

None

url: str#

The url of the response.

The value may be different than the url passed to fetch. See Response.url.

exception pyodide.http.HttpStatusError(status, status_text, url)#

A subclass of OSError raised by FetchResponse.raise_for_status() if the response status is 4XX or 5XX.

Parameters:
  • status (int) – The http status code of the request

  • status_text (str) – The http status text of the request

  • url (str) – The url that was requested

pyodide.http.open_url(url)#

Fetches a given URL synchronously.

The download of binary files is not supported. To download binary files use pyodide.http.pyfetch() which is asynchronous.

It will not work in Node unless you include a polyfill for XMLHttpRequest

Parameters:

url (str) – URL to fetch

Return type:

StringIO

Returns:

The contents of the URL.

Examples

>>> None 
>>> import pytest; pytest.skip("TODO: Figure out how to skip this only in node")
>>> url = "https://cdn.jsdelivr.net/pyodide/v0.24.1/full/pyodide-lock.json"
>>> url_contents = open_url(url)
>>> import json
>>> result = json.load(url_contents)
>>> sorted(list(result["info"].items()))
[('arch', 'wasm32'), ('platform', 'emscripten_3_1_45'), ('python', '3.11.3'), ('version', '0.24.1')]
async pyodide.http.pyfetch(request, /, *, signal=None, fetcher=None, **kwargs)#

Fetch the url and return the response.

This functions provides a similar API to fetch() however it is designed to be convenient to use from Python. The FetchResponse has methods with the output types already converted to Python objects.

Parameters:
  • request (str | Request) – Either a string URL or a JavaScript Request object to fetch.

  • signal (Any) – Abort signal to use for the fetch request.

  • fetcher (Any) – Fetcher to use for the fetch request.

  • **kwargs (Any) – keyword arguments are passed along as optional parameters to the fetch API.

Return type:

FetchResponse

Examples

>>> import pytest; pytest.skip("Can't use top level await in doctests")
>>> res = await pyfetch("https://cdn.jsdelivr.net/pyodide/v0.23.4/full/repodata.json")
>>> res.ok
True
>>> res.status
200
>>> data = await res.json()
>>> data
{'info': {'arch': 'wasm32', 'platform': 'emscripten_3_1_32',
'version': '0.23.4', 'python': '3.11.2'}, ... # long output truncated