Sending JSON vs Form Data in Python Requests

Feb 3, 2024 ยท 2 min read

When making HTTP requests in Python using the requests module, you can send request bodies in different formats like JSON or form-urlencoded data. However, sometimes the request body is sent incorrectly or unexpectedly as JSON even if you want to send form data.

The Difference Between JSON and Form Data

JSON (JavaScript Object Notation) is a lightweight data format that looks like JavaScript objects. For example:

{"key1": "value1", "key2": "value2"} 

Form-urlencoded data is essentially key-value pairs encoded in a URL format, like:


Servers can handle both JSON and form data, but they need to be parsed differently on the backend.

Why Requests May Send JSON Instead of Form Data

By default, if you pass a dict to the data parameter in Requests, it will get JSON encoded automatically:

import requests

data = {'key1': 'value1', 'key2': 'value2'}

r =, json=data) # Sends JSON

So if you want to send form data instead, you need to explicitly use the data parameter instead of json:

import requests

data = {'key1': 'value1', 'key2': 'value2'}  

r =, data=data) # Sends form data

The key thing to remember is that Requests handles JSON encoding for you, but not form encoding. So use json for JSON and data with a dict for form data.

Hope this helps explain why sometimes Requests may send JSON even if you expect it to send form-urlencoded data!

Browse by tags:

Browse by language:

The easiest way to do Web Scraping

Get HTML from any page with a simple API call. We handle proxy rotation, browser identities, automatic retries, CAPTCHAs, JavaScript rendering, etc automatically for you

Try ProxiesAPI for free

curl ""

<!doctype html>
    <title>Example Domain</title>
    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />


Don't leave just yet!

Enter your email below to claim your free API key: