HTTP client in Swift: making requests correctly from A to Z

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: why it's important to know how to work with HTTP in Swift

\n

Modern mobile and desktop applications rarely exist in isolation. Almost any application — from a weather widget to a banking client — exchanges data with a server. The HTTP protocol is used for this, and on the Swift side (iOS/macOS), the main tool is the Foundation framework and its URLSession class.

\n

In this article, we will break down how to properly create an HTTP client in Swift: from a simple GET request to complex error handling and working with JSON. The material will be useful both for beginners just getting acquainted with iOS development, and for experienced developers looking to systematize their knowledge.

\n

We will look at the modern approach using async/await (Swift 5.5+), which makes code clean and readable, and also touch on classic methods with closures (completion handlers) for backward compatibility.

\n\n

URLSession Basics: Creation and Configuration

\n

The URLSession class is the main "conductor" of network requests in Swift. It manages connections, caching, and authentication. Before making requests, you need to create a session instance.

\n\n

Session Types

\n
    \n
  • Shared (singleton): URLSession.shared — a simple session without customization. Suitable for basic requests.
  • \n
  • Default: URLSession(configuration: .default) — allows you to configure timeouts, cache, and headers.
  • \n
  • Ephemeral: URLSession(configuration: .ephemeral) — does not save cache and cookies to disk. Ideal for private data.
  • \n
  • Background: URLSession(configuration: .background(withIdentifier:)) — for background downloading/uploading data, even when the app is minimized.
  • \n
\n\n
import Foundation\n\n// Simple session\nlet sharedSession = URLSession.shared\n\n// Custom session with 30 second timeout\nlet config = URLSessionConfiguration.default\nconfig.timeoutIntervalForRequest = 30\nconfig.timeoutIntervalForResource = 60\nlet customSession = URLSession(configuration: config)\n
\n\n

Creating and Sending HTTP Requests

\n

A request is formed using the URLRequest class. It contains the URL, HTTP method, headers, and request body. Let's look at the main methods: GET and POST.

\n\n

GET request with async/await (modern approach)

\n

Starting with Swift 5.5, Apple added support for asynchronous functions (async/await). This is the most concise and safe way to work with the network.

\n\n
func fetchData(from urlString: String) async throws -> Data {\n    guard let url = URL(string: urlString) else {\n        throw URLError(.badURL)\n    }\n    \n    var request = URLRequest(url: url)\n    request.httpMethod = "GET"\n    request.setValue("application/json", forHTTPHeaderField: "Accept")\n    \n    let (data, response) = try await URLSession.shared.data(for: request)\n    \n    // Check HTTP status\n    guard let httpResponse = response as? HTTPURLResponse,\n          (200...299).contains(httpResponse.statusCode) else {\n        throw URLError(.badServerResponse)\n    }\n    \n    return data\n}\n\n// Usage:\nTask {\n    do {\n        let data = try await fetchData(from: "https://api.example.com/users")\n        print("Received \\(data.count) bytes")\n    } catch {\n        print("Error: \\(error.localizedDescription)")\n    }\n}\n
\n\n

POST request with JSON body

\n

To send data to the server, the POST method is used. The request body is usually encoded in JSON.

\n\n
struct User: Codable {\n    let name: String\n    let email: String\n}\n\nfunc createUser(_ user: User) async throws -> Data {\n    let url = URL(string: "https://api.example.com/users")!\n    var request = URLRequest(url: url)\n    request.httpMethod = "POST"\n    request.setValue("application                

Blogs

Book Recommendations