HTTP Fundamentals & the http Package
HTTP Fundamentals & the http Package
Almost every real-world Flutter application communicates with a remote server: fetching user profiles, loading product catalogues, posting form data, or streaming live updates. All of this happens over HTTP (HyperText Transfer Protocol) — the foundation of data exchange on the web. Before writing a single line of Dart networking code, you need a solid mental model of how HTTP works.
The Request / Response Cycle
Every HTTP interaction follows the same pattern: a client (your Flutter app) sends a request to a server, and the server replies with a response. Each message carries two parts:
- Headers — metadata about the message (content type, authorisation token, cache directives, accepted encodings, etc.)
- Body — the actual payload (JSON, HTML, binary data, or empty)
A typical GET request to a REST API looks like this at the protocol level:
Raw HTTP Request & Response (conceptual)
// REQUEST (client → server)
GET /users/42 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer eyJhbGci...
// RESPONSE (server → client)
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 87
{"id":42,"name":"Edrees","email":"edrees@example.com","role":"admin"}
HTTP Methods
HTTP defines several request methods (also called verbs) that communicate intent to the server:
- GET — retrieve a resource; no body; safe & idempotent
- POST — create a new resource or submit data; has a body; not idempotent
- PUT — replace a resource entirely; idempotent
- PATCH — partially update a resource
- DELETE — remove a resource
Status Codes
The server always replies with a three-digit status code that tells you whether the request succeeded and why it might have failed. Every Flutter developer must know the key ranges:
- 2xx Success —
200 OK,201 Created,204 No Content - 3xx Redirection —
301 Moved Permanently,304 Not Modified - 4xx Client Error —
400 Bad Request,401 Unauthorized,403 Forbidden,404 Not Found,422 Unprocessable Entity - 5xx Server Error —
500 Internal Server Error,503 Service Unavailable
"status" or "error" fields your API returns.Adding the http Package to Flutter
Dart's standard library has no built-in HTTP client suited for Flutter apps. The official solution is the http package, maintained by the Dart team. Add it to your project with one command:
Adding the Dependency
// Terminal — run in your project root:
flutter pub add http
// This adds the following line to pubspec.yaml:
// dependencies:
// http: ^1.2.1
// Then import it in any Dart file:
import 'package:http/http.dart' as http;
The as http alias is the community convention. It prevents name collisions and makes every call site explicit — http.get(), http.post(), etc.
Android & iOS Network Permissions
On mobile platforms the OS enforces network security rules at the OS level, not just in code:
- Android — add
<uses-permission android:name="android.permission.INTERNET" />toandroid/app/src/main/AndroidManifest.xml. Most Flutter templates include this automatically. - iOS — App Transport Security (ATS) blocks plain HTTP by default. Stick to
https://in production; for local dev only you can add an ATS exception inios/Runner/Info.plist.
Making Your First GET Request
The http.get() function returns a Future<http.Response>. Use async/await to keep the code readable. Always check response.statusCode before touching response.body.
First GET Request — Fetching a User
import 'dart:convert';
import 'package:http/http.dart' as http;
Future<Map<String, dynamic>> fetchUser(int id) async {
final uri = Uri.parse('https://jsonplaceholder.typicode.com/users/$id');
final response = await http.get(
uri,
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_TOKEN',
},
);
if (response.statusCode == 200) {
// response.body is a raw String; decode it to a Map
return jsonDecode(response.body) as Map<String, dynamic>;
} else {
throw Exception(
'Failed to fetch user. Status: ${response.statusCode}',
);
}
}
Understanding the Response Object
The http.Response returned by every call exposes these key properties:
statusCode— integer (e.g.200)body— the raw response body as a UTF-8StringbodyBytes— the body as aUint8List(for binary data)headers— aMap<String, String>of response headersreasonPhrase— human-readable status text (e.g."OK")
Uri.parse() or the Uri.https() / Uri.http() constructors instead of passing raw strings. The constructor variants automatically handle URL encoding of query parameters, which prevents hard-to-debug encoding bugs when values contain spaces or special characters.Summary
In this lesson you learned that HTTP is a request/response protocol where the client sends a verb (GET, POST…) plus headers and an optional body, and the server replies with a status code and a body. You added the http package via flutter pub add http, imported it with the standard as http alias, and wrote your first async GET request that checks the status code and decodes the JSON body. In the next lesson you will model that JSON as typed Dart classes using the model / fromJson pattern.