Skip to content

F# Guide — HTTP: Making Web Requests

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about F# Guide. We cover key concepts, practical examples, and best practices to help you master this topic.

F# HTTP programming uses .NET's HttpClient for modern async HTTP operations and FSharp.Data HTTP utilities for simpler request-response patterns with JSON integration.

What You'll Learn

  • Using HttpClient in F#
  • Async HTTP requests
  • JSON API integration
  • Authentication and headers
  • Error handling for HTTP

Why It Matters

HTTP is the foundation of web API communication. Durga Antivirus Pro uses HTTP for cloud signature updates and API integration.

Real-World Use

REST API clients, web scraping, microservice communication, and cloud service integration.

flowchart LR
    A["HTTP"] --> B["HttpClient"]
    B --> C["Async Requests"]
    C --> D["JSON APIs"]
    D --> E["Error Handling"]
    A:::current --> B
    style A fill:#2563eb,stroke:#2563eb,color:#fff
    style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style E fill:#f1f5f9,stroke:#94a3b8,color:#64748b

Basic HttpClient

open System.Net.Http

let httpClient = new HttpClient()

let getString url = task {
    let! response = httpClient.GetStringAsync(url)
    return response
}

// Usage
let html = getString "http://example.com" |> Async.AwaitTask |> Async.RunSynchronously

Async HTTP with FSharp.Data

open FSharp.Data

// Simple HTTP request
let html = Http.RequestString("http://example.com")

// With headers
let result = Http.RequestString(
    "http://api.example.com/data",
    headers = ["Authorization", "Bearer token"],
    httpMethod = "GET"
)

POST Requests

open System.Net.Http
open System.Text

let postJson url jsonContent = task {
    let content = new StringContent(jsonContent, Encoding.UTF8, "application/json")
    let! response = httpClient.PostAsync(url, content)
    let! responseBody = response.Content.ReadAsStringAsync()
    return responseBody
}

// Usage
let response = postJson "http://api.example.com/users" """{"name":"Alice","email":"a@example.com"}"""

HTTP with FSharp.Data

open FSharp.Data

// GET with JSON response
let weather = Http.RequestString("https://api.weather.gov/points/45.52,-122.68",
    headers = ["User-Agent", "F# App"])
)

// POST with JSON
let postResult = Http.Request(
    "http://api.example.com/users",
    body = TextRequest """{"name":"Alice"}""",
    httpMethod = "POST",
    headers = ["Content-Type", "application/json"]
)

Authentication

// Basic auth
let basicAuth username password =
    let credentials = sprintf "%s:%s" username password
    let encoded = System.Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials))
    sprintf "Basic %s" encoded

let requestWithAuth = task {
    httpClient.DefaultRequestHeaders.Authorization <-
        System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "mytoken")
    let! response = httpClient.GetStringAsync("http://api.example.com/protected")
    return response
}

Error Handling

let safeHttpGet url = task {
    try
        let! response = httpClient.GetAsync(url)
        if response.IsSuccessStatusCode then
            let! content = response.Content.ReadAsStringAsync()
            return Ok content
        else
            return Error (sprintf "HTTP %d: %s" (int response.StatusCode) response.ReasonPhrase)
    with
    | :? HttpRequestException as ex ->
        return Error (sprintf "Request failed: %s" ex.Message)
    | :? TaskCanceledException ->
        return Error "Request timed out"
}

Common Mistakes

1. Not disposing HttpClient

Create and dispose HttpClient properly. Use use client = new HttpClient() or reuse a single instance.

2. Blocking on async calls

Calling .Result or .Wait() blocks threads. Use let! in async/task CEs.

3. Ignoring status codes

Always check response.IsSuccessStatusCode before reading content.

4. No timeout handling

Set a timeout: httpClient.Timeout <- TimeSpan.FromSeconds(30).

5. Not handling network errors

Network failures throw exceptions. Always wrap HTTP calls in try-with.

Practice Questions

1. How do you make a GET request in F#? Use HttpClient.GetStringAsync or Http.RequestString from FSharp.Data.

2. How do you send JSON in a POST request? Create a StringContent with JSON string and application/json content type.

3. How do you add authentication headers? Set httpClient.DefaultRequestHeaders.Authorization or pass headers in the request.

Challenge: Write an async function that fetches data from a paginated API and returns all results.

FAQ

{{< faq question="Should I use HttpClient or FSharp.Data.Http?" >} HttpClient is the modern standard with full async support. FSharp.Data.Http is simpler for quick scripts. {{< /faq >}}

{{< faq question="How do I handle redirects?" >} HttpClient follows redirects by default. Disable with Handler.AllowAutoRedirect = false if needed. {{< /faq >}}

{{< faq question="Can I download files with HTTP?" >} Yes. Use httpClient.GetByteArrayAsync for binary data or httpClient.GetStreamAsync for streaming. {{< /faq >}}

{{< faq question="How do I set custom headers?" >} Set on DefaultRequestHeaders for all requests or pass per-request headers with HttpRequestMessage. {{< /faq >}}

{{< faq question="Is there a way to mock HTTP in tests?" >} Yes. Use HttpClient with a mock HttpMessageHandler for Unit Testing. {{< /faq >}}

Mini Project

Build a GitHub API client:

open System.Net.Http
open System.Text.Json

type GitHubUser = { login: string; name: string; public_repos: int }

let client = new HttpClient()
client.DefaultRequestHeaders.UserAgent.ParseAdd("FSharp-App")

let getUser username = task {
    let! json = client.GetStringAsync($"https://api.github.com/users/{username}")
    let user = JsonSerializer.Deserialize<GitHubUser>(json)
    return user
}

// Usage
let user = getUser "dotnet" |> Async.AwaitTask |> Async.RunSynchronously
printfn "%s has %d repos" user.name user.public_repos

What's Next

Now that you understand HTTP clients, explore unit testing in F#.

Topic Description Link
F# Testing Unit testing {{< ref "26-testing" >}}
F# .NET Interop C# interop {{< ref "27-net-interop" >}}

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro