When sending HTTP requests with Python's requests
library, understanding the difference between the json
and data
parameters is crucial for proper API communication. These parameters control how your payload is formatted and what content type headers are sent.
Quick Comparison
| Parameter | Content-Type | Use Case | Format |
|-----------|-------------|----------|--------|
| data
| application/x-www-form-urlencoded
| HTML forms, traditional web APIs | Dict, tuples, bytes, or strings |
| json
| application/json
| REST APIs, modern web services | JSON-serializable Python objects |
The data
Parameter
The data
parameter sends form-encoded data, which is the traditional format used by HTML forms. When you use data
, requests automatically sets the Content-Type
header to application/x-www-form-urlencoded
.
Accepted Data Types
- Dictionary: Automatically form-encoded
- List of tuples: Allows duplicate keys
- Bytes: Raw data sent as-is
- String: Raw data sent as-is
Examples
import requests
# Dictionary - most common usage
form_data = {'username': 'john', 'password': 'secret123'}
response = requests.post('https://httpbin.org/post', data=form_data)
# List of tuples - useful for duplicate keys
form_tuples = [('tag', 'python'), ('tag', 'web'), ('category', 'tutorial')]
response = requests.post('https://httpbin.org/post', data=form_tuples)
# Raw string data
raw_form = 'username=john&password=secret123'
response = requests.post('https://httpbin.org/post', data=raw_form)
# Bytes data
byte_data = b'username=john&password=secret123'
response = requests.post('https://httpbin.org/post', data=byte_data)
Form Data with Files
# Sending form data with file uploads
files = {'file': open('document.pdf', 'rb')}
form_data = {'description': 'Important document', 'category': 'legal'}
response = requests.post('https://httpbin.org/post', data=form_data, files=files)
The json
Parameter
The json
parameter sends JSON-formatted data, which is the standard for REST APIs and modern web services. When you use json
, requests automatically:
- Sets Content-Type
header to application/json
- Serializes your Python object to JSON string using json.dumps()
Accepted Data Types
- Dictionary: Most common usage
- List: For JSON arrays
- Any JSON-serializable object: Strings, numbers, booleans, None
Examples
import requests
# Dictionary - converted to JSON object
json_data = {
'user': {
'name': 'John Doe',
'email': 'john@example.com',
'preferences': ['email', 'sms']
},
'action': 'create_account'
}
response = requests.post('https://api.example.com/users', json=json_data)
# List - converted to JSON array
json_array = [
{'id': 1, 'name': 'Product A'},
{'id': 2, 'name': 'Product B'}
]
response = requests.post('https://api.example.com/products', json=json_array)
# Simple values
response = requests.post('https://api.example.com/status', json={'active': True})
Real-World Usage Examples
HTML Form Submission
# Traditional web form login
login_data = {
'username': 'user@example.com',
'password': 'mypassword',
'remember_me': 'on'
}
response = requests.post('https://example.com/login', data=login_data)
REST API Call
# Creating a user via REST API
user_data = {
'name': 'Jane Smith',
'email': 'jane@example.com',
'role': 'admin',
'metadata': {
'department': 'Engineering',
'hire_date': '2024-01-15'
}
}
response = requests.post('https://api.example.com/users', json=user_data)
Common Mistakes to Avoid
❌ Don't Use Both Parameters
# This is wrong - don't use both simultaneously
requests.post('https://api.example.com', data=form_data, json=json_data)
❌ Don't Manually Set Content-Type with json Parameter
# This is unnecessary - requests handles it automatically
headers = {'Content-Type': 'application/json'}
requests.post('https://api.example.com', json=data, headers=headers)
❌ Don't Send JSON String to data Parameter
import json
# This sends JSON as form data (usually not what you want)
json_string = json.dumps(data)
requests.post('https://api.example.com', data=json_string)
When to Use Which Parameter
Use data
when:
- Submitting HTML forms
- Working with legacy APIs expecting form data
- Uploading files (combined with files
parameter)
- The API specifically requires application/x-www-form-urlencoded
Use json
when:
- Working with REST APIs
- Sending complex nested data structures
- The API expects JSON format
- Building modern web applications
Debugging Tips
You can inspect what's being sent by examining the request:
import requests
# Prepare the request without sending it
req = requests.Request('POST', 'https://httpbin.org/post', json={'key': 'value'})
prepared = req.prepare()
print(f"Content-Type: {prepared.headers.get('Content-Type')}")
print(f"Body: {prepared.body}")
Understanding these differences ensures your HTTP requests are properly formatted for the target API, preventing common integration issues and improving your application's reliability.