When building mobile or web applications with Dart—especially using the Flutter framework—making HTTP requests to REST APIs is a routine task. However, handling errors effectively during these operations is essential for creating reliable and user-friendly applications. In this guide, you’ll learn how to manage HTTP errors properly in Dart using the http
package, covering timeout handling, client/server-side error responses, and exception types.

Why Error Handling Matters
Without proper error handling, your app might crash or behave unexpectedly when the API is down, the user has no internet connection, or the server returns a 500 error. Proper error handling ensures your application fails gracefully and provides helpful feedback to the user.
Installing the HTTP Package
Make sure you have the http
package added in your pubspec.yaml
:
dependencies: http: ^0.13.6
Making HTTP Requests with Error Handling
Here is a complete example that includes:
- HTTP GET request
- Timeout exception
- Socket exception
- HTTP status code validation
File: api_service.dart
import 'dart:convert'; import 'dart:io'; import 'package:http/http.dart' as http; class ApiService { final String baseUrl = 'https://jsonplaceholder.typicode.com'; Future<dynamic> fetchData(String endpoint) async { final url = Uri.parse('$baseUrl/$endpoint'); try { final response = await http.get(url).timeout(const Duration(seconds: 10)); if (response.statusCode >= 200 && response.statusCode < 300) { return jsonDecode(response.body); } else { throw HttpException('Server responded with status: ${response.statusCode}'); } } on SocketException { throw Exception('No Internet connection.'); } on HttpException catch (e) { throw Exception('HTTP error: ${e.message}'); } on FormatException { throw Exception('Bad response format.'); } on TimeoutException { throw Exception('The connection has timed out.'); } } }
File: main.dart
import 'package:flutter/material.dart'; import 'api_service.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'HTTP Error Handling Demo', home: Scaffold( appBar: AppBar(title: const Text('API Error Handling')), body: const Center(child: DataDisplay()), ), ); } } class DataDisplay extends StatefulWidget { const DataDisplay({super.key}); @override State<DataDisplay> createState() => _DataDisplayState(); } class _DataDisplayState extends State<DataDisplay> { final ApiService _apiService = ApiService(); String _result = 'Fetching data...'; @override void initState() { super.initState(); _loadData(); } void _loadData() async { try { final data = await _apiService.fetchData('posts/1'); setState(() { _result = data.toString(); }); } catch (e) { setState(() { _result = 'Error: $e'; }); } } @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(16.0), child: Text(_result), ); } }
This code provides a robust and reusable pattern for HTTP requests in Dart, catching various error scenarios cleanly.
To deepen your understanding of HTTP error codes and best practices in API response management, check out this MDN Web Docs guide.