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:

  • 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.

import requests

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

import os
import requests

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.

import requests

url = "https://api.example.com/users/123"
headers = {"Authorization": "Bearer YOUR_TOKEN"}

try:
    response = requests.get(url, headers=headers, timeout=10)

    if response.status_code == 401:
        print("Unauthorized. Check your token.")
    elif response.status_code == 404:
        print("Not found. Check the URL or ID.")
    else:
        response.raise_for_status()
        print(response.json())

except requests.exceptions.Timeout:
    print("Request timed out. Try again or increase the timeout.")
except requests.exceptions.RequestException as e:
    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.

import requests

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

import requests

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.

import requests

headers = {"Authorization": "Bearer YOUR_TOKEN"}
page = 1
all_users = []

while True:
    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", []))

    if not data.get("has_more"):
        break

    page += 1

print("users:", len(all_users))

Example 3: Handle rate limiting (429) with a short wait

import time
import requests

headers = {"Authorization": "Bearer YOUR_TOKEN"}
url = "https://api.example.com/reports"

r = requests.get(url, headers=headers, timeout=10)

if r.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.

import requests

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.

import json
from urllib.request import Request, urlopen

url = "https://api.example.com/status"
req = Request(url, headers={"Accept": "application/json"})

with urlopen(req, timeout=10) as resp:
    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

import requests
import json

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:

import requests

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

import requests

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:

import requests

r = requests.get("https://api.example.com/secret", timeout=10)

if r.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() for GET and requests.post() for POST.
  • 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.