flutter-use-http-package — Flutter skill for REST API requests
This skill shows how to send GET, POST, PUT, and DELETE requests with Flutter's http package and handle JSON responses. Use it when an app needs to read from or write to a REST API.
npx skills add flutter/agent-plugins --skill flutter-use-http-package -a claude-codeWhat flutter-use-http-package does
The skill walks through requests with the http package: parsing a URL, setting headers, and encoding JSON for POST and PUT. It maps responses to typed Dart models with a fromJson factory, checks the status code, and throws on failure so FutureBuilder can display an error state.
For expensive JSON parsing, it uses compute() in a background isolate. The parsing function must be top-level or static. The guide also covers connecting the future to FutureBuilder and handling loading, data, and error states. Android needs the internet permission in android/app/src/main/AndroidManifest.xml; macOS needs the network client key in both entitlement files. Check these platform settings before testing requests, since missing permissions can block network access.
What it helps with
- send JSON to a REST API with POST or PUT
- fetch data with GET and query parameters
- map a JSON response to a typed Dart model
- show request failures through
FutureBuilder - move expensive JSON parsing to an isolate
Example prompts for the agent
- Add a GET request with `http` to my Flutter app and display the result with `FutureBuilder`.
- Implement a POST request with a JSON body, check the status code, and parse the response into a Dart model.
- Use `compute()` to parse this large JSON response and check the Android network permission.
How to install flutter-use-http-package
1Skills CLI (Vercel)
npx skills add flutter/agent-plugins --skill flutter-use-http-package -a claude-code2Manually: put the files in place
~/.claude/skills/flutter-use-http-package/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/flutter-use-http-package/
1Skills CLI (Vercel)
npx skills add flutter/agent-plugins --skill flutter-use-http-package -a codex2Manually: put the files in place
.agents/skills/flutter-use-http-package/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add flutter/agent-plugins --skill flutter-use-http-package -a cursor2Manually: put the files in place
.cursor/skills/flutter-use-http-package/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install flutter/agent-plugins flutter-use-http-package2Manually: put the files in place
.github/skills/flutter-use-http-package/SKILL.md1Skills CLI (Vercel)
npx skills add flutter/agent-plugins --skill flutter-use-http-package -a gemini-cli2Platform CLI
gemini skills install https://github.com/flutter/agent-plugins --path skills/flutter-use-http-packageManually: put the files in place
.devin/skills/flutter-use-http-package/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add flutter/agent-plugins --skill flutter-use-http-package -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
From the same set7
The whole set →Similar
Questions about flutter-use-http-package
How do I install flutter-use-http-package in Claude Code?
Run npx skills add flutter/agent-plugins --skill flutter-use-http-package -a claude-code. The skill file is at ~/.claude/skills/flutter-use-http-package/SKILL.md.
What does flutter-use-http-package do?
It guides an agent through HTTP requests with the http package, status handling, and mapping JSON into Dart models. It also covers displaying results and errors with FutureBuilder.
Which network settings does it cover for Android and macOS?
For Android, add android.permission.INTERNET to android/app/src/main/AndroidManifest.xml. For macOS, add com.apple.security.network.client to macos/Runner/DebugProfile.entitlements and macos/Runner/Release.entitlements.
Source text
SKILL.md · BSD-3-Clause
---
name: flutter-use-http-package
description: Use the `http` package to execute GET, POST, PUT, or DELETE requests. Use when you need to fetch from or send data to a REST API.
metadata:
model: models/gemini-3.1-pro-preview
last_modified: Tue, 21 Apr 2026 21:36:42 GMT
---
# Implementing Flutter Networking
## Contents
- [Configuration & Permissions](#configuration--permissions)
- [Request Execution & Response Handling](#request-execution--response-handling)
- [Background Parsing](#background-parsing)
- [Workflow: Executing Network Operations](#workflow-executing-network-operations)
- [Examples](#examples)
## Configuration & Permissions
Configure the environment and platform-specific permissions required for network access.
1. Add the `http` package dependency via the terminal:
```bash
flutter pub add http
```
2. Import the package in your Dart files:
```dart
import 'package:http/http.dart' as http;
```
3. Configure Android permissions by adding the Internet permission to `android/app/src/main/AndroidManifest.xml`:
```xml
<uses-permission android:name="android.permission.INTERNET" />
```
4. Configure macOS entitlements by adding the network client key to both `macos/Runner/DebugProfile.entitlements` and `macos/Runner/Release.entitlements`:
```xml
<key>com.apple.security.network.client</key>
<true/>
```
## Request Execution & Response Handling
Execute HTTP operations and map responses to strongly typed Dart objects.
* **URIs:** Always parse URL strings using `Uri.parse('your_url')`.
* **Headers:** Inject authorization and content-type headers via the `headers` parameter map. Use `HttpHeaders.authorizationHeader` for auth tokens.
* **Payloads:** For POST and PUT requests, encode the body using `jsonEncode()` from `dart:convert`.
* **Status Validation:** Evaluate `response.statusCode`. Treat `200 OK` (GET/PUT/DELETE) and `201 CREATED` (POST) as success.
* **Error Handling:** Throw explicit exceptions for non-success status codes. Never return `null` on failure, as this prevents `FutureBuilder` from triggering its error state and causes infinite loading indicators.
* **Deserialization:** Parse the raw string using `jsonDecode(response.body)` and map it to a custom Dart object using a factory constructor (e.g., `fromJson`).
## Background Parsing
Offload expensive JSON parsing to a separate Isolate to prevent UI jank (frame drops).
* Import `package:flutter/foundation.dart`.
* Use the `compute()` function to run the parsing logic in a background isolate.
* Ensure the parsing function passed to `compute()` is a top-level function or a static method, as closures or instance methods cannot be passed across isolates.
## Workflow: Executing Network Operations
Use the following checklist to implement and validate network operations.
**Task Progress:**
- [ ] 1. Define the strongly typed Dart model with a `fromJson` factory constructor.
- [ ] 2. Implement the network request method returning a `Future<Model>`.
- [ ] 3. Apply conditional logic based on the operation type:
- **If fetching data (GET):** Append query parameters to the URI.
- **If mutating data (POST/PUT):** Set `'Content-Type': 'application/json; charset=UTF-8'` and attach the `jsonEncode` body.
- **If deleting data (DELETE):** Return an empty model instance on success (`200 OK`).
- [ ] 4. Validate the `statusCode` and throw an `Exception` on failure.
- [ ] 5. Integrate the `Future` into the UI using `FutureBuilder`.
- [ ] 6. Handle `snapshot.hasData`, `snapshot.hasError`, and default to a `CircularProgressIndicator`.
- [ ] 7. **Feedback Loop:** Run the app -> trigger the network request -> review console for unhandled exceptions -> fix parsing or permission errors.
## Examples
### High-Fidelity Implementation: Fetching and Parsing in the Background
```dart
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
// 1. Top-level parsing function for Isolate
List<Photo> parsePhotos(String responseBody) {
final parsed = (jsonDecode(responseBody) as List<Object?>)
.cast<Map<String, Object?>>();
return parsed.map<Photo>(Photo.fromJson).toList();
}
// 2. Network execution with background parsing
Future<List<Photo>> fetchPhotos() async {
final response = await http.get(
Uri.parse('https://jsonplaceholder.typicode.com/photos'),
headers: {
HttpHeaders.authorizationHeader: 'Bearer your_token_here',
HttpHeaders.acceptHeader: 'application/json',
},
);
if (response.statusCode == 200) {
// Offload heavy parsing to a background isolate
return compute(parsePhotos, response.body);
} else {
throw Exception('Failed to load photos. Status: ${response.statusCode}');
}
}
// 3. Strongly typed model
class Photo {
final int id;
final String title;
final String thumbnailUrl;
const Photo({
required this.id,
required this.title,
required this.thumbnailUrl,
});
factory Photo.fromJson(Map<String, dynamic> json) {
return Photo(
id: json['id'] as int,
title: json['title'] as String,
thumbnailUrl: json['thumbnailUrl'] as String,
);
}
}
// 4. UI Integration
class PhotoGallery extends StatefulWidget {
const PhotoGallery({super.key});
@override
State<PhotoGallery> createState() => _PhotoGalleryState();
}
class _PhotoGalleryState extends State<PhotoGallery> {
late Future<List<Photo>> _futurePhotos;
@override
void initState() {
super.initState();
// Initialize Future once to prevent re-fetching on rebuilds
_futurePhotos = fetchPhotos();
}
@override
Widget build(BuildContext context) {
return FutureBuilder<List<Photo>>(
future: _futurePhotos,
builder: (context, snapshot) {
if (snapshot.hasData) {
final photos = snapshot.data!;
return ListView.builder(
itemCount: photos.length,
itemBuilder: (context, index) => ListTile(
leading: Image.network(photos[index].thumbnailUrl),
title: Text(photos[index].title),
),
);
} else if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
// Default loading state
return const Center(child: CircularProgressIndicator());
},
);
}
}
```
© flutter · BSD-3-Clause · flutter/agent-plugins