The runtime:net module provides HTTP networking capabilities with capability-based access control.
Network access must be declared in manifest.app.toml:
[capabilities.net]
fetch = ["https://api.example.com/*", "https://cdn.example.com/*"]Glob patterns for URL matching:
*- matches any characters except/**- matches any characters including/
Fetch a URL and return response as text:
import { fetch } from "runtime:net";
const response = await fetch("https://api.example.com/data");
console.log(response.status); // 200
console.log(response.ok); // true
console.log(response.body); // Response body as string
console.log(response.headers); // { "content-type": "application/json" }Options:
| Option | Type | Default | Description |
|---|---|---|---|
method |
string |
"GET" |
HTTP method |
headers |
Record<string, string> |
{} |
Request headers |
body |
string |
- | Request body |
timeout_ms |
number |
30000 |
Timeout in milliseconds |
Returns:
interface FetchResponse {
status: number;
statusText: string;
headers: Record<string, string>;
body: string;
url: string;
ok: boolean; // true if status 200-299
}Fetch a URL and return response as raw bytes:
import { fetchBytes } from "runtime:net";
const response = await fetchBytes("https://example.com/image.png");
const imageData = response.body; // Uint8ArrayReturns:
interface FetchBytesResponse {
status: number;
statusText: string;
headers: Record<string, string>;
body: Uint8Array;
url: string;
ok: boolean;
}Fetch a URL and parse response as JSON:
import { fetchJson } from "runtime:net";
interface User {
id: number;
name: string;
email: string;
}
const user = await fetchJson<User>("https://api.example.com/users/1");
console.log(user.name);POST JSON data to a URL:
import { postJson } from "runtime:net";
const response = await postJson("https://api.example.com/users", {
name: "John Doe",
email: "john@example.com"
});
console.log(response.status); // 201const response = await fetch("https://api.example.com/items");
const items = JSON.parse(response.body);const response = await fetch("https://api.example.com/items", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ name: "New Item" })
});const response = await fetch("https://api.example.com/protected", {
headers: {
"Authorization": "Bearer your-token-here"
}
});const response = await fetch("https://slow-api.example.com/data", {
timeout_ms: 60000 // 60 seconds
});import { fetch } from "runtime:net";
try {
const response = await fetch("https://api.example.com/data");
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = JSON.parse(response.body);
} catch (error) {
if (error.message.includes("permission")) {
console.error("URL not allowed - check capabilities");
} else if (error.message.includes("timeout")) {
console.error("Request timed out");
} else {
console.error("Network error:", error);
}
}import { fetchJson, postJson } from "runtime:net";
import { notify } from "runtime:sys";
interface WeatherData {
temperature: number;
description: string;
humidity: number;
}
async function getWeather(city: string): Promise<WeatherData> {
try {
const data = await fetchJson<WeatherData>(
`https://api.weather.com/v1/current?city=${encodeURIComponent(city)}`
);
return data;
} catch (error) {
await notify("Weather Error", `Failed to fetch weather: ${error.message}`);
throw error;
}
}
async function reportAnalytics(event: string, data: unknown): Promise<void> {
try {
await postJson("https://analytics.example.com/events", {
event,
data,
timestamp: Date.now()
});
} catch (error) {
// Silent fail for analytics
console.warn("Analytics failed:", error);
}
}