Using Python's socket Library to Simulate HTTP Requests: Basic and Advanced Examples
This article explains how to use Python's socket module to craft and send raw HTTP GET, POST, and custom‑header requests, then shows how to encapsulate the logic into reusable classes that handle authentication, redirects, cookies, and HTTPS, providing a low‑level networking toolkit for developers.
The introduction explains that using Python's socket library to simulate HTTP requests bypasses high‑level libraries like requests , giving deeper insight into the HTTP protocol and fine‑grained control over request details.
Basic Example – Sending an HTTP GET request
import socket
def send_http_get_request(host, port, path="/"):
# Create a socket object
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# Connect to the server
client_socket.connect((host, port))
# Prepare HTTP request message
request = f"GET {path} HTTP/1.1\r\nHost: {host}\r\nConnection: close\r\n\r\n"
# Send request
client_socket.sendall(request.encode())
# Receive response
response = b""
while True:
part = client_socket.recv(1024)
if not part:
break
response += part
# Print response
print(response.decode())
finally:
# Close connection
client_socket.close()
send_http_get_request('www.example.com', 80)Basic Example – Sending an HTTP POST request
import socket
def send_http_post_request(host, port, path="/", data=""):
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
client_socket.connect((host, port))
request = f"POST {path} HTTP/1.1\r\nHost: {host}\r\nContent-Length: {len(data)}\r\nConnection: close\r\n\r\n{data}"
client_socket.sendall(request.encode())
response = b""
while True:
part = client_socket.recv(1024)
if not part:
break
response += part
print(response.decode())
finally:
client_socket.close()
send_http_post_request('www.example.com', 80, '/submit', 'key=value')Basic Example – Sending a request with custom headers
import socket
def send_custom_headers_request(host, port, path="/", headers=None):
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
client_socket.connect((host, port))
request = f"GET {path} HTTP/1.1\r\nHost: {host}"
if headers:
for key, value in headers.items():
request += f"\r\n{key}: {value}"
request += "\r\nConnection: close\r\n\r\n"
client_socket.sendall(request.encode())
response = b""
while True:
part = client_socket.recv(1024)
if not part:
break
response += part
print(response.decode())
finally:
client_socket.close()
headers = {'User-Agent': 'CustomBrowser', 'Accept-Encoding': 'gzip, deflate'}
send_custom_headers_request('www.example.com', 80, '/', headers)The notes section reminds readers about default ports (80 for HTTP, 443 for HTTPS), UTF‑8 encoding, timeout handling, and more robust error handling for production use.
Advanced Example – Encapsulating HTTP logic in a class
import socket
class HttpSocketClient:
def __init__(self, host, port=80, timeout=10):
self.host = host
self.port = port
self.timeout = timeout
self.socket = None
def connect(self):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.settimeout(self.timeout)
self.socket.connect((self.host, self.port))
def send(self, request):
self.socket.sendall(request.encode())
def receive(self):
response = b""
while True:
part = self.socket.recv(1024)
if not part:
break
response += part
return response.decode()
def close(self):
if self.socket:
self.socket.close()
def execute_request(self, request):
self.connect()
self.send(request)
response = self.receive()
self.close()
return response
# Usage example
client = HttpSocketClient('www.example.com')
request = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: close\r\n\r\n"
response = client.execute_request(request)
print(response)Advanced Example – Adding Basic Authentication
import base64
class AuthenticatedHttpSocketClient(HttpSocketClient):
def __init__(self, host, port=80, username=None, password=None, timeout=10):
super().__init__(host, port, timeout)
self.username = username
self.password = password
def build_request(self, method, path, headers=None, body=None):
request = f"{method} {path} HTTP/1.1\r\n"
request += f"Host: {self.host}\r\n"
if self.username and self.password:
auth_header = f"Basic {base64.b64encode(f'{self.username}:{self.password}'.encode()).decode()}"
request += f"Authorization: {auth_header}\r\n"
if headers:
for k, v in headers.items():
request += f"{k}: {v}\r\n"
if body:
request += f"Content-Length: {len(body)}\r\n\r\n{body}"
else:
request += "\r\n"
return request
# Usage example
client = AuthenticatedHttpSocketClient('www.example.com', username='user', password='pass')
request = client.build_request('GET', '/')
response = client.execute_request(request)
print(response)Advanced Example – Automatic Redirect Handling
from urllib.parse import urlparse
class RedirectHandlingHttpSocketClient(HttpSocketClient):
def follow_redirects(self, request, max_redirects=5):
redirects_count = 0
while redirects_count < max_redirects:
response = self.execute_request(request)
status_line = response.split('\r\n')[0]
status_code = int(status_line.split()[1])
if 300 <= status_code < 400:
location_header = self.get_location_header(response)
if location_header:
url = urlparse(location_header)
self.host = url.netloc
request = f"GET {url.path} HTTP/1.1\r\nHost: {self.host}\r\nConnection: close\r\n\r\n"
redirects_count += 1
else:
raise ValueError("Redirect missing Location header.")
else:
return response
raise ValueError("Too many redirects.")
def get_location_header(self, response):
for line in response.split('\r\n')[1:]:
if line.startswith('Location:'):
return line[len('Location:'):]
return None
# Usage example
client = RedirectHandlingHttpSocketClient('www.example.com')
request = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: close\r\n\r\n"
response = client.follow_redirects(request)
print(response)Advanced Example – Cookie Management
import re
class CookieHandlingHttpSocketClient(HttpSocketClient):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.cookies = {}
def handle_cookies(self, response):
cookie_header = self.extract_cookie_header(response)
if cookie_header:
for cookie in cookie_header.split('; '):
name, value = cookie.split('=')
self.cookies[name] = value
def extract_cookie_header(self, response):
for line in response.split('\r\n')[1:]:
if line.startswith('Set-Cookie:'):
return line[len('Set-Cookie:'):]
return None
def build_request(self, method, path, headers=None, body=None):
request = super().build_request(method, path, headers, body)
if self.cookies:
cookie_header = '; '.join([f"{k}={v}" for k, v in self.cookies.items()])
request = request.replace('\r\n', f"\r\nCookie: {cookie_header}\r\n", 1)
return request
# Usage example
client = CookieHandlingHttpSocketClient('www.example.com')
request = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: close\r\n\r\n"
response = client.execute_request(request)
client.handle_cookies(response)
print(client.cookies)Advanced Example – HTTPS Support
import ssl
class SecureHttpSocketClient(HttpSocketClient):
def connect(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(self.timeout)
self.socket = ssl.wrap_socket(sock)
self.socket.connect((self.host, self.port))
# Usage example
client = SecureHttpSocketClient('www.example.com', port=443)
request = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: close\r\n\r\n"
response = client.execute_request(request)
print(response)The summary reiterates that these examples demonstrate how to build, extend, and reuse socket‑based HTTP clients in Python, covering authentication, redirects, cookies, and secure HTTPS connections, thereby providing a flexible foundation for low‑level network testing and automation.
Test Development Learning Exchange
Test Development Learning Exchange
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.