How to Build and Test HTTP Requests Without Writing Code
This guide has a free tool → Open JWT Decoder
Why Test HTTP Requests?
Every web application communicates through HTTP. Whether you are building a REST API, integrating a third-party service, debugging a webhook, or exploring an undocumented API, you need to send HTTP requests and inspect the responses.
Understanding what goes into an HTTP request - and what comes back - is one of the most fundamental skills in modern web development. Without it, API integration becomes a guessing game and debugging becomes an exercise in frustration.
Traditionally, developers use several tools for this:
- cURL - powerful and scriptable but the syntax is hard to remember, especially for complex requests with headers and JSON bodies
- Postman - feature-rich but requires installation, an account, and has grown increasingly complex for simple tasks
- Browser DevTools - excellent for inspecting existing traffic but not designed for crafting custom requests
- Insomnia - lighter than Postman but still requires installation
Sometimes you just want a lightweight tool that lets you build a request visually, send it, and see the response. No installation, no account, no configuration file to maintain.
JWT Decoder
Free online JWT decoder - decode and inspect JSON Web Tokens without sending them to a server
Base64 Encoder/Decoder
Base64 encode and decode online - convert text to Base64 or decode Base64 strings instantly, free
JSON Formatter
JSON formatter and validator online - format, beautify, and validate JSON data instantly in your browser
The Anatomy of an HTTP Request
Before you can build good HTTP requests, you need to understand what they consist of.
Every HTTP request has four parts:
METHOD /path?query=params HTTP/1.1
Host: example.com
Header-Name: header-value
Header-Name: header-value
request body (for POST, PUT, PATCH)Method - what action to take (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)
URL - where to send the request, including the path and optional query parameters
Headers - metadata about the request: authentication, content type, accepted formats, caching preferences
Body - the data payload (only for methods that include a body)
Understanding all four parts lets you read and write requests correctly, diagnose problems precisely, and communicate clearly with API documentation.
HTTP Methods Explained
GET
Retrieves data from a server. GET requests should never modify data - they are read-only by convention and by HTTP specification.
GET /api/users?page=1&limit=10&sort=created_at HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGci...
Accept: application/jsonUse GET for: fetching resources, search queries, listing data, pagination.
GET requests have no body. All parameters go in the URL as query strings.
POST
Sends data to create a new resource or trigger an action.
POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGci...
{
"name": "Alice",
"email": "alice@example.com",
"role": "editor"
}Use POST for: creating records, submitting forms, uploading files, triggering actions (like sending an email), authentication (submitting login credentials).
PUT
Replaces an entire resource with the provided data. If you PUT a user with only a name field, the API may erase all other fields.
PUT /api/users/123 HTTP/1.1
Content-Type: application/json
{
"name": "Alice Smith",
"email": "alice.smith@example.com",
"role": "admin",
"department": "engineering"
}Use PUT for: full updates where you send the complete object representation.
PATCH
Partially updates a resource - only the fields you include are changed. Fields you omit remain untouched.
PATCH /api/users/123 HTTP/1.1
Content-Type: application/json
{
"email": "new.email@example.com"
}Use PATCH for: partial updates where you only want to modify specific fields. PATCH is preferred over PUT when you do not have or need the full object.
DELETE
Removes a resource. Usually has no body, though some APIs accept a body for batch deletes.
DELETE /api/users/123 HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGci...Use DELETE for: deleting individual records, batch operations when supported.
HEAD
Identical to GET but returns only the headers, no response body. Useful for checking if a resource exists or getting its metadata without downloading the full content.
HEAD /api/users/123 HTTP/1.1Use HEAD for: checking if a URL exists (link validation), getting file size before download, checking Last-Modified date for caching.
OPTIONS
Returns the allowed HTTP methods for a URL. Browsers automatically send OPTIONS preflight requests before CORS requests to check whether the cross-origin request is permitted.
OPTIONS /api/users HTTP/1.1
Host: api.example.com
Origin: https://app.example.com
Access-Control-Request-Method: POSTHTTP Method Summary
| Method | Has Body | Idempotent | Safe | Use Case |
|---|---|---|---|---|
| GET | No | Yes | Yes | Retrieve resource |
| POST | Yes | No | No | Create resource |
| PUT | Yes | Yes | No | Full replacement |
| PATCH | Yes | No | No | Partial update |
| DELETE | No | Yes | No | Delete resource |
| HEAD | No | Yes | Yes | Get headers only |
| OPTIONS | No | Yes | Yes | CORS preflight |
Idempotent means calling the same request multiple times produces the same result. PUT is idempotent (setting a user's name to "Alice" ten times produces the same outcome). POST is not (creating a user ten times creates ten users).
Safe means the request does not modify server state. GET and HEAD are safe - they only read.
HTTP Headers You Should Know
Headers carry metadata about the request and response. Understanding common headers makes debugging much faster.
Request Headers
| Header | Purpose | Example |
|---|---|---|
Content-Type | Format of the request body | application/json |
Authorization | Authentication credentials | Bearer eyJhbGci... |
Accept | Desired response format | application/json |
Accept-Language | Preferred language | en-US, en;q=0.9 |
User-Agent | Client identification | MyApp/1.0 (Node.js) |
Cache-Control | Caching directives | no-cache |
If-Modified-Since | Conditional GET | Wed, 01 Jan 2025 00:00:00 GMT |
X-Request-ID | Tracing identifier | req_a1b2c3d4 |
Idempotency-Key | Prevent duplicate operations | idem_xyz789 |
Response Headers
| Header | Purpose | Example |
|---|---|---|
Content-Type | Format of the response body | application/json; charset=utf-8 |
X-RateLimit-Limit | Requests allowed per window | 1000 |
X-RateLimit-Remaining | Requests left in current window | 847 |
X-RateLimit-Reset | When the window resets (Unix timestamp) | 1740000000 |
Location | Redirect URL or created resource URL | https://api.example.com/users/456 |
Set-Cookie | Set a browser cookie | session=abc123; HttpOnly; Secure |
Access-Control-Allow-Origin | CORS policy | https://app.example.com |
ETag | Resource version identifier for caching | "a1b2c3d4e5f6" |
Last-Modified | Timestamp of last modification | Wed, 01 Jan 2025 00:00:00 GMT |
Retry-After | When to retry after rate limit | 60 |
Content-Type Values
application/json - JSON data
application/x-www-form-urlencoded - HTML form data
multipart/form-data - File uploads
text/plain - Plain text
text/html - HTML
application/xml - XML data
application/octet-stream - Binary dataGetting Content-Type wrong is a common source of bugs. If you send JSON with Content-Type: application/x-www-form-urlencoded, the server will parse your request body incorrectly and return confusing errors.
HTTP Status Codes
Status codes tell you what happened with your request. They are grouped into five classes by the first digit.
2xx - Success
| Code | Meaning | When You See It |
|---|---|---|
| 200 | OK | Request succeeded; response body contains data |
| 201 | Created | POST succeeded; new resource created |
| 202 | Accepted | Request accepted for async processing |
| 204 | No Content | Success with no response body (common on DELETE) |
| 206 | Partial Content | Range request succeeded (file downloads, streaming) |
3xx - Redirection
| Code | Meaning | When You See It |
|---|---|---|
| 301 | Moved Permanently | Resource has a new permanent URL |
| 302 | Found | Temporary redirect |
| 304 | Not Modified | Cached version is still valid; no body returned |
| 307 | Temporary Redirect | Like 302 but preserves the HTTP method |
| 308 | Permanent Redirect | Like 301 but preserves the HTTP method |
4xx - Client Error
| Code | Meaning | Common Cause |
|---|---|---|
| 400 | Bad Request | Malformed JSON, missing required fields, invalid parameter |
| 401 | Unauthorized | Missing or invalid authentication token |
| 403 | Forbidden | Authenticated but not permitted to access this resource |
| 404 | Not Found | Resource does not exist at this URL |
| 405 | Method Not Allowed | Using POST on a GET-only endpoint |
| 409 | Conflict | Duplicate entry, optimistic locking failure |
| 410 | Gone | Resource was permanently deleted |
| 422 | Unprocessable Entity | Valid syntax but semantic validation failed |
| 429 | Too Many Requests | Rate limit exceeded |
| 451 | Unavailable For Legal Reasons | Rare but exists |
5xx - Server Error
| Code | Meaning | Common Cause |
|---|---|---|
| 500 | Internal Server Error | Unhandled exception on the server |
| 502 | Bad Gateway | Upstream server returned invalid response |
| 503 | Service Unavailable | Server overloaded or in maintenance mode |
| 504 | Gateway Timeout | Upstream server did not respond in time |
Understanding Authentication Schemes
Most production APIs require authentication. Here are the common schemes and how to send them:
Bearer Token (JWT)
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...JWT tokens contain encoded claims you can inspect without contacting the server. Use the JWT Decoder to decode a token and check its expiry, scope, and payload.
API Key
Depending on the API, the key may go in a header or a query parameter:
# Header
X-API-Key: sk_live_a1b2c3d4e5f6
# Query parameter (less secure)
GET /api/data?api_key=sk_live_a1b2c3d4e5f6Basic Authentication
Username and password, base64-encoded:
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=The encoded value is base64("username:password"). Use the Base64 tool to encode credentials manually. Never use Basic Auth over plain HTTP - always HTTPS only.
OAuth 2.0
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=abc&client_secret=xyz&scope=read:usersThe response includes an access token you then use as a Bearer token for subsequent API requests.
Query Parameters vs Request Body
A common source of confusion is knowing when to use query parameters versus a request body.
Query parameters go in the URL after ?:
GET /api/users?status=active&page=2&limit=25&sort=name&order=ascUse query parameters for:
- Filtering and searching
- Pagination
- Sorting and ordering
- Non-sensitive configuration options
Request body is attached to POST, PUT, PATCH:
{
"name": "Alice",
"email": "alice@example.com",
"role": "admin"
}Use the body for:
- Data being created or updated
- Anything sensitive (never put passwords or tokens in query parameters - they appear in server logs)
- Large amounts of data
Common API Debugging Scenarios
"I keep getting 401 Unauthorized"
- Check whether the
Authorizationheader is present in the request - Verify the token format - Bearer tokens need the
Bearerprefix:Bearer eyJ... - Decode the token with the JWT Decoder - check if it is expired (the
expclaim) - Confirm you are hitting the right environment - a staging token will not work against a production endpoint
- Check whether the token has the required scope for this endpoint
- Verify the token was issued for the correct audience (
audclaim in JWT)
"CORS errors in the browser"
CORS (Cross-Origin Resource Sharing) errors occur when your JavaScript tries to request a resource from a different origin (different domain, port, or protocol). This is a browser security feature - cURL and server-to-server requests are not subject to CORS.
// This will fail with CORS error if the server does not allow it
const res = await fetch('https://api.other-domain.com/data');Solutions:
- The server must add
Access-Control-Allow-Originheaders that include your origin - Use a proxy in development to forward requests through your own origin
- Test API behavior (not CORS) using a non-browser HTTP client
"The API returns 200 but the data is wrong"
- Log the exact request being sent - are the parameters correct?
- Check the
Content-Typeheader - sending JSON withoutContent-Type: application/jsonmay cause the server to parse the body incorrectly - Verify the request body with a JSON Formatter to ensure it is valid JSON
- Compare your request against the API documentation or a known-good example using the Diff Checker
- Check whether you are hitting a cached response - add
Cache-Control: no-cacheto the request
"I get 400 Bad Request but the body looks right"
- Validate your JSON - a trailing comma or missing quote will cause a parse error. Use the JSON Formatter to validate
- Check required fields - the API may require fields that the documentation does not obviously highlight
- Check data types -
"age": "25"(string) will fail if the API expects"age": 25(number) - Check whether the endpoint expects
application/jsonorapplication/x-www-form-urlencoded
"The API returns 429 Too Many Requests"
- Read the
Retry-Afterresponse header - it tells you how many seconds to wait - Read
X-RateLimit-LimitandX-RateLimit-Remainingto understand your quota - Implement exponential backoff in your code rather than retrying immediately
- Cache responses where possible to reduce API calls
Reading API Responses
Response Body
Most modern APIs return JSON. Check the Content-Type response header to confirm the format before parsing.
{
"data": {
"id": 123,
"name": "Alice",
"email": "alice@example.com"
},
"meta": {
"request_id": "req_a1b2c3",
"timestamp": "2026-03-02T10:00:00Z"
}
}Timing Information
When testing API performance, pay attention to:
- DNS lookup time - how long to resolve the hostname
- Connection time - TCP handshake duration
- TLS time - SSL/TLS negotiation (HTTPS only)
- Time to first byte (TTFB) - when the server started responding
- Total download time - full response received
Slow DNS or TLS times point to infrastructure issues. Slow TTFB points to server-side processing problems.
cURL Reference
For developers who prefer the command line, here is a cURL cheat sheet:
# GET request
curl https://api.example.com/users
# GET with headers
curl -H "Authorization: Bearer token123" \
-H "Accept: application/json" \
https://api.example.com/users
# POST with JSON body
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer token123" \
-d '{"name": "Alice", "email": "alice@example.com"}' \
https://api.example.com/users
# PATCH request
curl -X PATCH \
-H "Content-Type: application/json" \
-d '{"email": "new@example.com"}' \
https://api.example.com/users/123
# DELETE request
curl -X DELETE \
-H "Authorization: Bearer token123" \
https://api.example.com/users/123
# Show response headers only
curl -I https://api.example.com/users
# Follow redirects
curl -L https://api.example.com/redirect
# Save response to file
curl -o response.json https://api.example.com/data
# Verbose output (shows headers, timing)
curl -v https://api.example.com/usersThe main drawback of cURL for exploratory API work is that the syntax requires memorization and becomes unwieldy for complex requests with many headers and nested JSON bodies.
Fetch API in JavaScript
When implementing API calls in your application code:
// GET request
const response = await fetch('/api/users?page=1&limit=10', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
},
});
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const data = await response.json();
// POST request
const newUser = await fetch('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify({
name: 'Alice',
email: 'alice@example.com',
}),
});
// PATCH request
const updated = await fetch(`/api/users/${userId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify({ email: 'new@example.com' }),
});
// DELETE request
await fetch(`/api/users/${userId}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`,
},
});A robust fetch wrapper that handles errors consistently:
async function apiFetch(url, options = {}) {
const defaults = {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${getToken()}`,
},
};
const config = {
...defaults,
...options,
headers: {
...defaults.headers,
...options.headers,
},
};
const response = await fetch(url, config);
if (response.status === 204) {
return null; // No content
}
const data = await response.json();
if (!response.ok) {
const error = new Error(data.error?.message || 'API request failed');
error.status = response.status;
error.data = data;
throw error;
}
return data;
}
// Usage
try {
const user = await apiFetch('/api/users/123');
const updated = await apiFetch('/api/users/123', {
method: 'PATCH',
body: JSON.stringify({ email: 'new@example.com' }),
});
} catch (err) {
if (err.status === 401) {
redirectToLogin();
} else if (err.status === 429) {
scheduleRetry();
} else {
showError(err.message);
}
}Inspecting HTTP Traffic with Browser DevTools
The Network tab in browser DevTools lets you inspect every HTTP request your page makes:
- Open DevTools (
F12orCmd+Option+I) - Click the Network tab
- Reload the page or trigger the action
- Click any request to see: headers, request body, response body, timing
Right-click any request for useful options:
- "Copy as cURL" - copies the exact request as a cURL command you can run in your terminal
- "Copy as fetch" - copies the request as a JavaScript fetch() call
- "Block request URL" - simulate a failed request
Build Requests With ToolBox
The HTTP Request Builder lets you construct and test HTTP requests visually in your browser without installing anything:
- Choose the method - GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
- Enter the URL - the full endpoint you want to test
- Add headers - authentication tokens, content types, custom headers with a key-value interface
- Add a body - paste JSON, write form data, or input raw text for POST, PUT, PATCH requests
- Send - see the full response: status code, response headers, response body, and timing information
No installation, no account, no configuration files. Everything runs in your browser.
Complementary tools for API work:
- JWT Decoder - decode and inspect JWT tokens used in Authorization headers
- JSON Formatter - validate and format JSON request and response bodies
- Base64 tool - encode credentials for Basic Auth headers
- URL Encoder - encode query parameter values correctly
- Webhook Tester - test incoming webhook payloads
- API Mock Response Generator - generate mock API responses for frontend development
Try It Free
Build and test HTTP requests instantly in your browser. Free, private, no signup required.
Building mock APIs? Try the API Mock Response Generator. Need to test webhooks? Use the Webhook Tester. Working with JWT tokens? The JWT Decoder lets you inspect token contents without contacting the server.
Related Tools
Free, private, no signup required
Regex Tester
Free online regex tester - test and debug regular expressions with live matching and highlights
Text Diff Checker
Free online text diff checker - compare two texts and see the differences highlighted line by line
Code Formatter
Free online code formatter - beautify and format JavaScript, CSS, HTML, and more
You might also like
Want higher limits, batch processing, and AI tools?