(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisbon

How to speed up API calls with requests.Session

João Barros 10 de July de 2026 4 min read

Making many API calls with requests.get() opens and closes a connection every single time, wasting time on TCP and TLS handshakes. With the requests.Session object you reuse the same connection and set headers and authentication just once, keeping your code faster and cleaner. The difference really shows when you repeat calls to the same server inside a loop or in a service that runs around the clock.

Prerequisites

  • Python 3.9 or newer installed.
  • The requests library (install it with pip install requests).
  • A REST API to test against — we use the public https://httpbin.org, which returns JSON.
  • Knowing how to make a simple GET request.

Step 1: The cost of repeating requests.get()

Every time you call requests.get(), the library creates a new connection to the server, negotiates TLS (over HTTPS) and only then sends the request. Once or twice you won't notice; hundreds of times, the cost adds up. This is the common but inefficient pattern:

import requests

for user_id in range(1, 6):
    r = requests.get(f"https://httpbin.org/anything/{user_id}")
    print(r.status_code)

For a single request this is perfectly fine — the problem appears when you repeat the request many times. On each pass of the loop a connection is opened and closed. It works, but it gets slow as the number of API calls grows.

Step 2: Create a Session and reuse the connection

The requests.Session object keeps a pool of open connections (keep-alive). By using the same session for several requests to the same server, you avoid repeating the handshakes and gain speed almost for free:

import requests

with requests.Session() as session:
    for user_id in range(1, 6):
        r = session.get(f"https://httpbin.org/anything/{user_id}")
        print(r.status_code)

The with block makes sure the session is closed at the end and releases the connections. For the same server, this code is typically faster than Step 1, with no extra configuration.

Rule of thumb: create one session per external service and reuse it across your application, instead of calling requests.get() loosely over and over.

Step 3: Set headers and authentication once

With a session, you set common headers, tokens and parameters just once, and every request inherits them. This avoids repeating code and reduces mistakes:

session = requests.Session()
session.headers.update({
    "Authorization": "Bearer YOUR_TOKEN",
    "Accept": "application/json",
})

# Every request inherits the headers set above
r = session.get("https://httpbin.org/headers")
print(r.json())

The same idea applies to session.params, for fixed query parameters, and to session.auth, for basic authentication. Set it once, use it everywhere. If one day you need to change the token, you change it in a single place.

Step 4: Tune the connection pool

By default, requests keeps a small pool of connections. If you make many requests to the same server, you can grow that pool by mounting an HTTPAdapter on the session:

from requests.adapters import HTTPAdapter

adapter = HTTPAdapter(pool_connections=10, pool_maxsize=20)
session.mount("https://", adapter)
session.mount("http://", adapter)

pool_maxsize controls how many connections the pool keeps per host. A higher value helps mostly when you combine the session with threads to make calls in parallel. By default pool_maxsize is 10; raise it only if you really make concurrent calls.

Check the result

To confirm the connection is really being reused, turn on debug logging. With logging at the DEBUG level, urllib3 shows when it opens a new connection:

import logging
logging.basicConfig(level=logging.DEBUG)

with requests.Session() as session:
    for _ in range(3):
        session.get("https://httpbin.org/get")

You should see a single "Starting new HTTPS connection" message and then the following requests reusing it — instead of a new connection per request. That is the proof the session is working. If you still see several new-connection messages, check that you are using session.get() and not requests.get().

Conclusion

You moved from repeated requests.get() to a requests.Session that reuses connections, centralizes headers and lets you tune the pool — more speed and less duplicated code. The natural next step is to add automatic retries and timeouts to the session, so your API calls become robust too. Have you measured how much time you would save by reusing the connection in the API you use today?