Skip to content

[Bug]: Python APIRequestContext silently drops float and bool values supplied through dictionary-based multipart data #43185

Closed
microsoft/playwright-python
#3227

Description

@suraj-self

Version

1.62.1.dev18+g6b0021ec7

Steps to reproduce

Run:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    request = p.request.new_context()

    for value in [42.5, True, "hello"]:
        response = request.post(
            "https://httpbin.org/post",
            multipart={"value": value},
        )
        print(repr(value), "->", response.json()["form"])

    request.dispose()

Expected behavior

float and bool values accepted by the Python multipart type should be serialized as multipart form fields rather than silently dropped.

For example:

42.5 -> {'value': '42.5'}
True  -> {'value': 'true'}

Actual behavior

(env) ss@ss-Predator-PH315-53:~/playwright-python$ python abc.py
42.5 -> {}
True -> {}
'hello' -> {'value': 'hello'}
(env) ss@ss-Predator-PH315-53:~/playwright-python$

### Additional context

The Python implementation currently handles dictionary-based `multipart` values as follows:

```python
for name, value in multipart.items():
    if is_file_payload(value):
        ...
    elif isinstance(value, str):
        multipart_data.append(FormField(name=name, value=value))

There is no corresponding handling for float or bool, so those values fall through without generating a FormField.

The Python MultipartType explicitly includes these types:

MultipartType = Union[
    Dict[str, Union[bytes, bool, float, str, FilePayload]],
    FormData
]

The bundled JavaScript implementation handles the corresponding values and converts strings, numbers, and booleans to strings before creating the form field.

As an end-to-end comparison using the bundled Playwright Node runtime:

42.5 -> { value: '42.5' }
true -> { value: 'true' }
"hello" -> { value: 'hello' }

So the Python and JavaScript APIs currently behave differently for float and bool values supplied through dictionary-based multipart data.

Environment

System:
OS: Linux 6.8 Ubuntu 22.04.5 LTS 22.04.5 LTS (Jammy Jellyfish)
CPU: (16) x64 Intel(R) Core(TM) i7-10870H CPU @ 2.20GHz
Memory: 4.79 GB / 15.45 GB
Container: Yes
Binaries:
Node: 18.20.4 - /home/ss/.nvm/versions/node/v18.20.4/bin/node
Yarn: 1.22.22 - /home/ss/.nvm/versions/node/v18.20.4/bin/yarn
npm: 10.7.0 - /home/ss/.nvm/versions/node/v18.20.4/bin/npm
IDEs:
VSCode: 1.140.0 - /snap/bin/code
Languages:
Bash: 5.1.16 - /usr/bin/bash

Activity

  1. suraj-self commented on Oct 7, 2026

    @suraj-self
    Author

    If this issue is confirmed as a bug and is suitable for a community contribution, I’d be happy to work on the fix.

  2. alok-108 commented on Oct 7, 2026

    @alok-108
    Contributor

    Confirmed — this is indeed a bug in playwright-python.

    In playwright/_impl/_fetch.py (lines 426–438), when multipart is provided as a dictionary, only isinstance(value, str) and is_file_payload(value) were handled, causing int, float, and bool values to fall through and get silently dropped. In contrast, when multipart is a FormData instance, _form_data_field_to_form_field handles (str, int, float, bool).

    I've submitted a fix with regression tests on microsoft/playwright-python in PR microsoft/playwright-python#3226.

  3. suraj-self commented on Oct 7, 2026

    @suraj-self
    Author

    I have already reproduced and analysed the root cause, implemented and locally verified a minimal fix, including regression tests.

    Following Playwright’s contribution guidelines, I held off on opening a PR until the issue could be triaged/approved.

    I would like to work on the fix if the issue is approved for community contribution.

  4. pavelfeldman commented on Oct 7, 2026

    @pavelfeldman
    Member

    Go ahead with the Python fix

  5. suraj-self commented on Oct 7, 2026

    @suraj-self
    Author

    Go ahead with the Python fix

    Thank you, Pavel Feldman (@pavelfeldman) ! Really appreciate the go-ahead. I’ve opened the PR with the fix and regression tests. Please feel free to share any feedback when you have a chance. 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions