January 12, 2026
#3 - API Testing with requests
Part 3 of 5 · API Testing | Pytest & requests
Python requests module
requests is a high-level HTTP client for Python that lets you talk to APIs using simple, readable code instead of low-level networking.
What really happens when you call requests.get()
Below is a GET call with params — requests.get() is a wrapper to make an HTTP GET call:
response = requests.get(url="https://gorest.co.in/public/v2/users", params={"page": 2})Here's what happens behind the scenes for that call:

Internally this calls requests.api.request()
requests.api.get(url)
↓
requests.api.request("GET", url, **kwargs)A temporary session is created
- A new
Sessionobject is created - It exists only for this single request
- It is managed using a context manager
- It is automatically closed after the request completes
with sessions.Session() as session:
...A Request object is built
req = Request(
method="GET",
url="https://gorest.co.in/public/v2/users",
params={"page": 2}
)The request is prepared
- Query params are URL-encoded
?page=2is appended to the URL- Headers are merged and normalized
- Default headers like
User-Agentare added - Body (if any) is serialized
prepared_req = session.prepare_request(req)The prepared request is sent
- DNS lookup happens
- TCP connection is opened
- TLS handshake occurs (for HTTPS)
- HTTP request bytes are sent
- Server response is received
response = session.send(prepared_req)A Response object is created
Once the server replies, requests builds a Response object containing the status code, response headers, raw response body, timing information, and helper methods like .json().
The session is closed automatically
with Session() as session:
...Once the response is returned, the session is closed and connections are released.
API testing using requests and pytest
In this section we use the requests module to make API requests, process the response, add assertions, and execute everything using pytest.
Setup variables
BASE_URL = "https://gorest.co.in/public/v2"
USERS_ENDPOINT = f"{BASE_URL}/users"
USER_ENDPOINT = f"{USERS_ENDPOINT}/{{user_id}}"
TOKEN = os.environ.get("API_TOKEN")
headers = {"Authorization": f"Bearer {TOKEN}"}Create user flow
- Using Faker to create unique user data, to support repeated execution.
- The created user payload is a Python dictionary — but the API doesn't understand Python dictionaries.
- The
requestsmodule converts the Python dictionary to a JSON string viajson.dumps(create_user_payload)before sending the request, and appends the headerContent-Type: application/json— serialization. - To process the response body we convert response bytes back to a Python dictionary — deserialization — using
response_body = response.json(), which internally callsjson.loads(decoded_response_text).
def test_create_user():
# Create unique data for multiple execution
fake = Faker()
username = fake.name_male()
user_email = fake.email()
user_gender = "male"
user_status = "inactive"
# create user payload as python dict
create_user_payload = {
"name": username,
"email": user_email,
"gender": user_gender,
"status": user_status
}
# send POST request
response = requests.post(url=USERS_ENDPOINT, headers=headers, json=create_user_payload)
response_body = response.json()
print(f"Status Code: {response.status_code}")
print(f"Response Body: {response_body}")
# Assertion
assert response.status_code == 201
assert response_body["name"] == username
assert response_body["email"] == user_email
assert response_body["gender"] == user_gender
assert response_body["status"] == user_statusExecute the test using pytest and uv:
uv run pytest -s tests/test_gorest_crud.py::test_create_user
Test execution using pytest and uv
The rest of the test can be found in the gorest-api-test repository.
# Check uv is installed
uv --version
# Clone the repo
git clone https://github.com/sksingh329/gorest-api-test.git
# Switch to directory and branch
cd gorest-api-test
git switch basics/gorest-crud
# Install required packages
uv sync
# Export token
export API_TOKEN=<replace with your token>
# Run a specific test
uv run pytest -s tests/test_gorest_crud.py::test_create_user
# Run all tests
uv run pytestUsing requests to make API calls and pytest to execute tests provides foundational capability, but building scalable test suites requires additional infrastructure — shared utilities, pytest fixtures via conftest.py, and structured HTML reporting — which the next parts of this series cover.
Originally published on Hashnode.