How to Use API in Python
What you’ll build or solve
You’ll call a web API from Python, send parameters or JSON data, and read the response safely.
When this approach works best
Using an API in Python works well when you:
Learn Python on Mimo
- Pull data from a service, like user profiles, product catalogs, or exchange rates.
- Send data to a service, like creating a support ticket or logging an event.
- Automate a workflow, like syncing records between two tools on a schedule.
Avoid this approach when the data lives in a database you can access directly, or when a service provides an official SDK that already handles auth, retries, and pagination for you.
Prerequisites
- Python installed
- You know how to run a Python script
- Basic understanding of dictionaries (for JSON)
Step-by-step instructions
1) Make a GET request and read the response
Most APIs return JSON. Pass headers for auth and params for filtering.
importrequests
url="https://api.example.com/users"
headers= {"Authorization":"Bearer YOUR_TOKEN"}
params= {"limit":5}
response=requests.get(url,headers=headers,params=params,timeout=10)
response.raise_for_status()
print(response.json())
Option A: Store the token outside your code
importos
importrequests
token=os.environ.get("API_TOKEN","")
headers= {"Authorization":f"Bearer{token}"}
response=requests.get(
"https://api.example.com/users",
headers=headers,
params={"limit":5},
timeout=10,
)
response.raise_for_status()
print(response.json())
What to look for:
raise_for_status() turns HTTP errors into exceptions. Without it, a 401 or 404 can look “successful” until you try to use the response.
2) Handle API errors in a predictable way
APIs fail for normal reasons: bad credentials, missing resources, rate limits, and server errors.
importrequests
url="https://api.example.com/users/123"
headers= {"Authorization":"Bearer YOUR_TOKEN"}
try:
response=requests.get(url,headers=headers,timeout=10)
ifresponse.status_code==401:
print("Unauthorized. Check your token.")
elifresponse.status_code==404:
print("Not found. Check the URL or ID.")
else:
response.raise_for_status()
print(response.json())
exceptrequests.exceptions.Timeout:
print("Request timed out. Try again or increase the timeout.")
exceptrequests.exceptions.RequestExceptionase:
print("Request failed:",e)
What to look for:
A 429 status code usually means you hit a rate limit. Back off and retry later instead of sending more requests.
3) Send data with a POST request
For creating or updating data, APIs often expect JSON in the request body. Use json= so Python sends the right format.
importrequests
url="https://api.example.com/tickets"
headers= {"Authorization":"Bearer YOUR_TOKEN"}
payload= {
"title":"Login issue",
"priority":"high",
"customer_email":"mina@example.com",
}
response=requests.post(url,headers=headers,json=payload,timeout=10)
response.raise_for_status()
created=response.json()
print(created)
What to look for:
Some APIs return the created object. Others return only an ID or an empty body. If .json() fails, print response.text[:200].
Examples you can copy
Example 1: Simple health check
importrequests
r=requests.get("https://api.example.com/health",timeout=10)
print(r.status_code==200)
Example 2: Paginate until there are no more results
This example assumes the API uses page and has_more.
importrequests
headers= {"Authorization":"Bearer YOUR_TOKEN"}
page=1
all_users= []
whileTrue:
r=requests.get(
"https://api.example.com/users",
headers=headers,
params={"page":page,"limit":100},
timeout=10,
)
r.raise_for_status()
data=r.json()
all_users.extend(data.get("items", []))
ifnotdata.get("has_more"):
break
page+=1
print("users:",len(all_users))
Example 3: Handle rate limiting (429) with a short wait
importtime
importrequests
headers= {"Authorization":"Bearer YOUR_TOKEN"}
url="https://api.example.com/reports"
r=requests.get(url,headers=headers,timeout=10)
ifr.status_code==429:
wait_seconds=int(r.headers.get("Retry-After","5"))
time.sleep(wait_seconds)
r=requests.get(url,headers=headers,timeout=10)
r.raise_for_status()
print(r.json())
Example 4: Upload form data (not JSON)
Some APIs use form-encoded data for tokens or legacy endpoints.
importrequests
url="https://api.example.com/token"
payload= {"username":"demo","password":"demo"}
r=requests.post(url,data=payload,timeout=10)
r.raise_for_status()
print(r.json())
Example 5: Use urllib when you can’t install requests (stdlib only)
This is harder to read than requests, but it works on a locked-down system.
importjson
fromurllib.requestimportRequest,urlopen
url="https://api.example.com/status"
req=Request(url,headers={"Accept":"application/json"})
withurlopen(req,timeout=10)asresp:
body=resp.read().decode("utf-8")
data=json.loads(body)
print(data)
Common mistakes and how to fix them
Mistake 1: Sending JSON as a string in data=
What you might do
importrequests
importjson
payload= {"name":"Naomi"}
r=requests.post(
"https://api.example.com/users",
data=json.dumps(payload)
)
Why it breaks
The server may treat the body as form data, or it may reject the content type.
Fix
Use json= so the request is encoded correctly:
importrequests
payload= {"name":"Naomi"}
r=requests.post(
"https://api.example.com/users",
json=payload,
timeout=10
)
r.raise_for_status()
print(r.json())
Mistake 2: Calling .json() on an error response
What you might do
importrequests
r=requests.get("https://api.example.com/secret",timeout=10)
print(r.json())
Why it breaks
The response might be HTML (like an error page) or an empty body. JSON parsing fails.
Fix
Check the status first, then parse:
Bash
importrequests
r=requests.get("https://api.example.com/secret",timeout=10)
ifr.ok:
print(r.json())
else:
print("Error:",r.status_code)
print(r.text[:200])
Troubleshooting
If you see ModuleNotFoundError: No module named 'requests', run pip install requests in the same environment you use to run Python.
If you get 401 Unauthorized, the token is missing, expired, or in the wrong header format. Double-check Authorization: Bearer ....
If you get 403 Forbidden, the token may lack permission, or the API blocks your IP or user agent.
If you get 404 Not Found, the endpoint path or resource ID is wrong, or the API version changed.
If you get 429 Too Many Requests, slow down. Use Retry-After if the server sends it.
If you get requests.exceptions.SSLError, a proxy or custom certificate may be involved. Try the same URL in a browser on the same network, then check proxy and certificate settings.
If .json() raises a JSONDecodeError, print response.text[:200] and confirm the API returns JSON for that request.
Quick recap
- Use
requests.get()forGETandrequests.post()forPOST. - Pass headers for auth, and
params=for query parameters. - Call
raise_for_status()to surface HTTP errors early. - Use
json=to send JSON bodies. - Handle common failures like 401, 404, 429, and timeouts with clear messages.
Join 35M+ people learning for free on Mimo
4.8 out of 5 across 1M+ reviews
Check us out on Apple AppStore, Google Play Store, and Trustpilot