Free tutorials & notes in Hindi & English · Clean code examples 🧰 Free PDF & Image Tools →
🟡 Advanced Python  ·  Lesson 28

API Requests in Python

In this lesson: Call REST APIs in Python with the requests library — GET, POST, JSON, headers and error handling — with output. In Hindi & English.

What is an API?

An API (Application Programming Interface) lets one program ask another program for data or actions over the internet. A weather app asks a weather API for today’s temperature; a shop app asks the server for products and sends orders back. Most web APIs speak HTTP and reply with JSON.

HTTP methodMeaningExample
GETRead dataList of products
POSTCreate somethingPlace an order
PUT / PATCHUpdateChange address
DELETERemoveCancel order

In this lesson we use the free CodingEasily practice API for a sweet shop: https://codingeasily.in/api/sweets/. It is real, needs no key and never stores your data, so you can experiment freely.

Terminal – install once (inside your venv)
pip install requests

Your first GET request

Python – get_products.py
import requests

URL = "https://codingeasily.in/api/sweets/"

response = requests.get(URL, timeout=10)
print("status :", response.status_code)
print("type   :", response.headers["Content-Type"])

products = response.json()           # JSON text → Python list of dicts
print("items  :", len(products))
for p in products[:3]:
    print(f"{p['id']}. {p['name']:<14} ₹{p['price']}/{p['unit']}  stock {p['stock']}")
status : 200 type : application/json; charset=utf-8 items : 8 1. Kaju Katli ₹900/kg stock 25 2. Malai Ghewar ₹650/kg stock 8 3. Rasmalai ₹700/kg stock 12
  • status_code 200 means OK.
  • .json() converts the reply into Python lists and dicts.
  • Always pass timeout=; without it a dead server can freeze your program forever.

Query parameters

Do not build URLs by joining strings. Pass a dictionary to params and requests encodes it correctly (spaces, Hindi, &).

Python – params.py
import requests

URL = "https://codingeasily.in/api/sweets/"

r = requests.get(URL, params={"category": "box"}, timeout=10)
print(r.url)
print([p["name"] for p in r.json()])

r = requests.get(URL, params={"q": "kaju"}, timeout=10)
print([p["name"] for p in r.json()])
https://codingeasily.in/api/sweets/?category=box ['Classic Gift Box', 'Assorted Gift Box'] ['Kaju Katli']

Status codes and errors

CodeMeaningWhat your program should do
200 / 201OK / CreatedUse the data
400 / 422Your request is wrongShow the server’s message to the user
401 / 403Not logged in / not allowedAsk for login or a valid API key
404Not foundShow “not found”
429Too many requestsWait and retry
500–599Server problemRetry later; log the error
Python – errors.py
import requests

URL = "https://codingeasily.in/api/sweets/"

def get_product(product_id):
    try:
        r = requests.get(URL, params={"id": product_id}, timeout=5)
        r.raise_for_status()                 # turns 4xx/5xx into an exception
        return r.json()
    except requests.exceptions.HTTPError:
        return f"HTTP {r.status_code}: {r.json().get('error')}"
    except requests.exceptions.Timeout:
        return "Server is too slow, try again"
    except requests.exceptions.ConnectionError:
        return "No internet connection"

print(get_product(2)["name"])
print(get_product(99))
Malai Ghewar HTTP 404: Product not found
⚠️ requests does not raise on 404 by itself

A 404 or 500 response is still a “successful” call. Call raise_for_status() or check r.ok before using the data.

Timeouts in practice

The practice API can simulate a slow server with ?delay= (milliseconds). Here the server needs 2 seconds but we wait only 1:

Python – timeout.py
import requests

URL = "https://codingeasily.in/api/sweets/"

try:
    requests.get(URL, params={"delay": 2000}, timeout=1)
except requests.exceptions.Timeout:
    print("Timed out after 1 second – show a friendly message instead of freezing")

r = requests.get(URL, params={"delay": 500}, timeout=5)
print("with a longer timeout:", r.status_code)
Timed out after 1 second – show a friendly message instead of freezing with a longer timeout: 200

POST: sending JSON (placing an order)

Python – post_order.py
import requests

URL = "https://codingeasily.in/api/sweets/"

order = {
    "name": "Aarti Gupta",
    "phone": "9829012345",
    "items": [{"id": 1, "qty": 0.5}, {"id": 7, "qty": 2}],
    "coupon": "SWEET10",
    "mode": "pickup",
}
r = requests.post(URL, json=order, timeout=10)     # json= sets the header and encodes for you
print(r.status_code)
data = r.json()
for item in data["items"]:
    print(f"  {item['name']:<17} x{item['qty']:<4} ₹{item['amount']}")
print("subtotal", data["subtotal"], "| discount", data["discount"], "| delivery", data["delivery"], "| total", data["total"])

bad = requests.post(URL, json={"name": "A", "phone": "12345", "items": []}, timeout=10)
print(bad.status_code, bad.json()["fields"])
201 Kaju Katli x0.5 ₹450 Classic Gift Box x2 ₹960 subtotal 1410 | discount 141 | delivery 0 | total 1269 422 {'name': 'Name must have at least 2 letters.', 'phone': 'Enter a valid 10-digit Indian mobile number.', 'items': 'Cart is empty.'}

The server validates everything and calculates the prices itself – the client only sends ids and quantities. That is how real e-commerce APIs protect against fake prices.

Headers, API keys and sessions

Python – session_headers.py
import os
import requests

session = requests.Session()                       # reuses the connection → faster
session.headers.update({
    "User-Agent": "school-report/1.0 (contact@example.com)",
    "Authorization": f"Bearer {os.environ.get('MY_API_KEY', 'demo-key')}",
})
r = session.get("https://codingeasily.in/api/sweets/", params={"id": 3}, timeout=10)
print(r.status_code, r.json()["name"])
print("sent header:", r.request.headers["User-Agent"])
200 Rasmalai sent header: school-report/1.0 (contact@example.com)
🔐 Never write API keys in code

Keep keys in environment variables or a .env file that is not committed to Git. A key pushed to GitHub is found by bots within minutes.

Automatic retries for unreliable servers

Python – retries.py
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

retry = Retry(total=3, backoff_factor=0.5, status_forcelist=[429, 500, 502, 503, 504])
session = requests.Session()
session.mount("https://", HTTPAdapter(max_retries=retry))
session.mount("http://", HTTPAdapter(max_retries=retry))

try:
    session.get("https://codingeasily.in/api/sweets/", params={"fail": 1}, timeout=5)
except requests.exceptions.RetryError:
    print("Gave up after 3 retries – the server keeps returning 500")
Gave up after 3 retries – the server keeps returning 500

?fail=1 makes the practice API return HTTP 500. The session retries 3 times with growing waits (0.5 s, 1 s, 2 s) before giving up.

Mini project: low-stock report

Python – low_stock_report.py
import csv
import requests

URL = "https://codingeasily.in/api/sweets/"

products = requests.get(URL, timeout=10).json()
low = sorted((p for p in products if p["stock"] < 15), key=lambda p: p["stock"])

with open("reorder.csv", "w", newline="", encoding="utf-8-sig") as f:
    w = csv.writer(f)
    w.writerow(["Product", "Stock", "Status"])
    for p in low:
        w.writerow([p["name"], p["stock"], "OUT OF STOCK" if p["stock"] == 0 else "Reorder"])

print(open("reorder.csv", encoding="utf-8-sig").read())
Product,Stock,Status Kalakand,0,OUT OF STOCK Malai Ghewar,8,Reorder Rasmalai,12,Reorder

Common mistakes

MistakeFix
No timeoutAlways timeout=10 (or a tuple (3, 10))
Using data without checking statusr.raise_for_status() or if r.ok:
data= instead of json= for JSON APIsUse json=payload
Building URLs with + and f-stringsUse params={...}
API key in code / GitHubEnvironment variable or .env (git-ignored)
Calling an API in a tight loopRespect rate limits; use sleep, caching or batch endpoints

Practice tasks

  1. Print all milk sweets (?category=milk) sorted by rating.
  2. Ask the user for a product id with input() and print its details or “not found”.
  3. Place a delivery order without a coupon and print the delivery charge returned by the server.
  4. Try a coupon on an order below ₹500 and print the server’s error message for the coupon field.

Summary

  • requests.get(url, params=…, timeout=…) reads; requests.post(url, json=…) sends JSON.
  • r.json() gives Python data; check r.status_code / raise_for_status().
  • Handle Timeout and ConnectionError; add retries for flaky servers.
  • Sessions reuse connections and headers; keep API keys out of code.

Frequently Asked Questions

Is requests built into Python?
No. Install it with pip install requests. The built-in alternative is urllib.request, which works but needs more code. requests is the most popular HTTP library for Python.
Why do I get an SSL error?
Usually the computer’s date/time is wrong, an office proxy intercepts HTTPS, or certificates are outdated. Fix the clock or update certifi with pip install --upgrade certifi. Do not use verify=False in real projects.
requests or httpx?
requests is simple and stable for normal scripts. httpx has a very similar API and also supports async and HTTP/2, which helps when you make many requests at the same time.
← Back to Python Tutorial
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

💻 Live Code Editor

This page's programs are ready here — run them, edit them, and learn. No installation needed.
Powered by OneCompiler. The code loads into the editor automatically — press Run to see the output. If the editor does not open, open it in a new tab.
Next topicTesting and Debugging Python Code Your progress: 28 / 66 (42%) · Lesson 29 / 66 Continue →

How was this lesson?

Your feedback helps us make the content better.

Write a review or suggestion (optional)

After approval, your name and city may appear publicly with your review. Please do not write your email or phone number.

▶ CodingEasily on YouTube

Learn with video lessons in easy Hindi

Featured video: RDBMS Part 3 – Class XI Commerce IT

▶ Subscribe – it’s free