Every language
15 languages, copy-ready. One at a time with syntax highlighting, or all inline.
SQLSQLrunnable
-- PostgreSQL + the community pgsql-http extension:
-- CREATE EXTENSION http; -- from PGXN or your distro's package
SELECT status,
content_type,
left(content, 80) AS body_preview
FROM http_get('https://jsonplaceholder.typicode.com/posts/1');
-- status | content_type | body_preview
-- -------+------------------------+------------------------------------------
-- 200 | application/json; ... | { "userId": 1, "id": 1, "title": "sunt ...Vanilla SQL opens no sockets — this is where SQL does NOT fit unaided. The Postgres community pgsql-http extension supplies http_get(); Supabase ships it, AWS RDS does not. Its result is ordinary rows (status, content_type, headers, content), so you can JOIN and filter on responses. MySQL/SqLite/SQL Server have no equivalent short of stored procedures shelling out.
JSJavaScript
const res = await fetch('https://jsonplaceholder.typicode.com/posts/1');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const post = await res.json();
console.log(res.status, post.title);Node 18+ and all browsers ship fetch(). It rejects ONLY on network failure — a 404 resolves happily, so res.ok (any 200–299) is the check you must write yourself. Node's fetch has NO default timeout: pass signal: AbortSignal.timeout(ms) before it hangs forever.
TSTypeScript
interface Post {
userId: number;
id: number;
title: string;
body: string;
}
const res = await fetch('https://jsonplaceholder.typicode.com/posts/1');
if (!res.ok) throw new Error(`HTTP ${res.status}`); // 404 is NOT a rejection
const post = (await res.json()) as Post; // cast = trust; validate if untrusted
console.log(res.status, post.title);
export {};Top-level await needs an ESM context ("type": "module" / .mts) — export {} marks the file as a module. res.json() is typed Promise<unknown> in lib.dom, so the `as Post` is trust, not validation; run untrusted bodies through a schema library (zod) instead. Same res.ok trap as plain JS.
GoGo
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
res, err := http.Get("https://jsonplaceholder.typicode.com/posts/1")
if err != nil {
panic(err) // transport failure only — a 404 is NOT an error in Go
}
defer res.Body.Close() // forgetting this leaks the connection
if res.StatusCode != http.StatusOK {
panic(fmt.Sprintf("HTTP %d", res.StatusCode))
}
body, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
fmt.Printf("%d %s\n", res.StatusCode, body)
}http.Get is shorthand for http.DefaultClient, which has NO timeout — fine for a demo, fatal in production (see the timeout snippet). err covers transport only: a 404 returns err == nil with the status on res, and skipping defer res.Body.Close() leaks the connection.
RsRust
fn main() -> Result<(), Box<dyn std::error::Error>> {
let res = reqwest::blocking::get("https://jsonplaceholder.typicode.com/posts/1")?;
let status = res.status();
let body = res.text()?;
if !status.is_success() {
return Err(format!("HTTP {status}").into());
}
println!("{status} {}", &body[..body.len().min(80)]);
Ok(())
}Cargo.toml: reqwest = { version = "0.12", features = ["blocking"] } — Rust has no stdlib HTTP. blocking::get is right for CLIs; servers want the async client under tokio. Like everywhere else, a 404 is Ok — res.error_for_status() is the built-in that converts it to Err.
PHPPHP
<?php
$ch = curl_init('https://jsonplaceholder.typicode.com/posts/1');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true, // without this the body PRINTS and exec returns true
CURLOPT_FOLLOWLOCATION => true,
]);
$body = curl_exec($ch);
if ($body === false) {
exit('cURL error: ' . curl_error($ch) . PHP_EOL); // transport failure only
}
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); // 4xx/5xx arrive here normally
if ($status >= 400) {
exit("HTTP $status" . PHP_EOL);
}
$post = json_decode($body, true);
echo $status, ' ', $post['title'], PHP_EOL;ext-curl ships with PHP and is the canonical HTTP story. CURLOPT_RETURNTRANSFER is the flag everyone forgets once — without it the body prints to stdout and curl_exec returns true. Handles self-close since PHP 8: curl_close() is deprecated (8.5) and does nothing. file_get_contents($url) plus $http_response_header is the zero-extension fallback.
PyPython
import json
import urllib.error
import urllib.request
url = "https://jsonplaceholder.typicode.com/posts/1"
try:
with urllib.request.urlopen(url) as res: # 4xx/5xx RAISE here
post = json.load(res)
print(res.status, post["title"])
except urllib.error.HTTPError as e:
print("HTTP", e.code) # e is still a response: e.read() has the bodyurllib.request is stdlib — no pip install. THE difference from JS fetch: urlopen RAISES urllib.error.HTTPError on 4xx/5xx — but the exception is itself a response object, so e.read() still holds the server's error body. The requests package is the ergonomic third-party favorite.
CC
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
typedef struct {
char data[4096];
size_t len;
} Body;
/* libcurl delivers the body in chunks — accumulate them yourself */
static size_t write_cb(char *chunk, size_t size, size_t nmemb, void *userdata) {
Body *body = userdata;
size_t bytes = size * nmemb;
size_t room = sizeof(body->data) - body->len - 1;
size_t fit = bytes < room ? bytes : room;
memcpy(body->data + body->len, chunk, fit);
body->len += fit;
return bytes; /* claim everything, or the transfer aborts */
}
int main(void) {
curl_global_init(CURL_GLOBAL_DEFAULT);
CURL *curl = curl_easy_init();
if (!curl) return 1;
Body body = {0};
curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts/1");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &body);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
CURLcode rc = curl_easy_perform(curl);
if (rc != CURLE_OK) { /* transport error — DNS, TLS, timeout */
fprintf(stderr, "curl: %s\n", curl_easy_strerror(rc));
curl_easy_cleanup(curl);
return 1;
}
long status = 0; /* a 404 gets here with rc == CURLE_OK — check it */
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
printf("HTTP %ld %.80s\n", status, body.data);
curl_easy_cleanup(curl);
curl_global_cleanup();
return 0;
}Compile with `cc main.c -o main -lcurl` — libcurl is the C ecosystem's HTTP answer, there is no stdlib one. The write callback receives the body in ARBITRARY chunks and must return the full byte count or the transfer aborts; 4xx/5xx still report CURLE_OK, so CURLINFO_RESPONSE_CODE is where the truth lands.
C++C++
#include <curl/curl.h>
#include <iostream>
#include <string>
static size_t write_cb(char* chunk, size_t size, size_t nmemb, void* userdata) {
auto* body = static_cast<std::string*>(userdata);
body->append(chunk, size * nmemb);
return size * nmemb; // must return the full count or the transfer aborts
}
int main() {
curl_global_init(CURL_GLOBAL_DEFAULT);
CURL* curl = curl_easy_init();
std::string body;
curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts/1");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &body);
if (CURLcode rc = curl_easy_perform(curl); rc != CURLE_OK) {
std::cerr << "curl: " << curl_easy_strerror(rc) << '\n';
return 1;
}
long status = 0; // 4xx/5xx still arrive as CURLE_OK — inspect the code
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
curl_easy_cleanup(curl);
curl_global_cleanup();
std::cout << status << ' ' << body.substr(0, 80) << '\n';
}libcurl is a C API — the std::string-append callback is the idiomatic C++ wrapper (cpr wraps libcurl in a native face if you want one). Same two rules as C: always return size * nmemb from the callback, and read CURLINFO_RESPONSE_CODE because CURLE_OK covers 404s.
C#C#
using System.Net.Http;
using var client = new HttpClient(); // fine for a script; services REUSE one instance
using var response = await client.GetAsync("https://jsonplaceholder.typicode.com/posts/1");
response.EnsureSuccessStatusCode(); // throws HttpRequestException on 4xx/5xx
string body = await response.Content.ReadAsStringAsync();
Console.WriteLine($"{(int)response.StatusCode} {body[..Math.Min(80, body.Length)]}");dotnet run (net6+): top-level statements plus top-level await. HttpClient is thread-safe and meant to be REUSED — one per process for scripts, IHttpClientFactory in ASP.NET Core, never per-request. EnsureSuccessStatusCode() throws on 4xx/5xx; check response.IsSuccessStatusCode when you'd rather branch than throw.
JvJava
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class GetRequest {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
.GET()
.build();
HttpResponse<String> res = client.send(request, HttpResponse.BodyHandlers.ofString());
if (res.statusCode() != 200) {
throw new RuntimeException("HTTP " + res.statusCode());
}
System.out.println(res.statusCode() + " " + res.body().substring(0, 80));
}
}java.net.http.HttpClient lives IN the JDK since 11 — no HttpURLConnection, no dependency. send() blocks the thread; sendAsync() returns a CompletableFuture. Same universal trap: non-2xx is a normal response, not an exception. The client is immutable — build one and reuse it.
SwSwift
import Foundation
struct Post: Decodable {
let title: String
}
let url = URL(string: "https://jsonplaceholder.typicode.com/posts/1")!
do {
let (data, response) = try await URLSession.shared.data(from: url)
let http = response as! HTTPURLResponse // always one over HTTP(S)
guard (200..<300).contains(http.statusCode) else {
throw URLError(.badServerResponse) // URLSession does NOT throw on 4xx/5xx
}
let post = try JSONDecoder().decode(Post.self, from: data)
print(http.statusCode, post.title)
} catch {
FileHandle.standardError.write("error: \(error)\n".data(using: .utf8)!)
exit(1)
}async/await flavor (Swift 5.5+, macOS 12/iOS 15) — call it from any Task or async context; the older dataTask(with:completionHandler:) still works everywhere. URLSession does NOT throw on 4xx/5xx — cast to HTTPURLResponse and read statusCode. data(from:) also enforces App Transport Security: http:// URLs need an Info.plist exception.
KtKotlin
import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
fun main() {
val client = HttpClient.newHttpClient() // JDK 11+ — no extra dependency
val request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
.build() // GET is the default method
val response = client.send(request, HttpResponse.BodyHandlers.ofString())
check(response.statusCode() == 200) { "HTTP ${response.statusCode()}" }
println("${response.statusCode()} ${response.body().take(80)}")
}No Kotlin-specific client needed: the JDK 11+ HttpClient is the idiomatic zero-dependency answer on the JVM (this file is `kotlinc`-clean). check{} turns the missing status check into an IllegalStateException carrying the code. ktor-client is the multiplatform option when you target non-JVM too.
RbRuby
require 'net/http'
require 'json'
uri = URI('https://jsonplaceholder.typicode.com/posts/1')
res = Net::HTTP.get_response(uri)
unless res.is_a?(Net::HTTPSuccess)
abort "HTTP #{res.code}"
end
post = JSON.parse(res.body)
puts "#{res.code} #{post['title']}"Net::HTTP is stdlib. get_response(uri) returns EVERY status for you to check; the shorter Net::HTTP.get(uri) instead RAISES on non-2xx, and res.value is the explicit raise-here call — pick one and be consistent. URI.open (open-uri) remains the one-liner for body slurps.
ZigZig
const std = @import("std");
pub fn main() !void {
var debug_allocator: std.heap.DebugAllocator(.{}) = .init;
defer _ = debug_allocator.deinit();
const allocator = debug_allocator.allocator();
var client: std.http.Client = .{ .allocator = allocator };
defer client.deinit();
var body: std.ArrayList(u8) = .empty; // 0.15: ArrayList is unmanaged
defer body.deinit(allocator);
const status = try client.fetch(.{
.location = .{ .url = "https://jsonplaceholder.typicode.com/posts/1" },
.response_storage = .{ .dynamic = &body },
});
if (status != .ok) return error.UnexpectedStatus;
std.debug.print("{d} {s}\n", .{ @intFromEnum(status), body.items[0..@min(body.items.len, 80)] });
}std.http.Client — in the stdlib since 0.11, and honest warning: the API reshuffles almost every release (this is 0.15's DebugAllocator + unmanaged ArrayList + fetch shape), so trust your toolchain's std docs over any snippet. Build with `zig build-exe main.zig`. fetch returns the Status enum; @intFromEnum gives the numeric code.