keecode logokeecode
Beginner
http methods
http verbs
get post put delete
http request methods
rest methods
api methods

HTTP Methods Explained: GET, POST, PUT, DELETE and More

Complete beginner's guide to HTTP methods (verbs). Learn what GET, POST, PUT, PATCH, and DELETE do, when to use each, and see practical examples.

Updated January 15, 2025

HTTP methods (also called HTTP verbs) tell the server what action you want to perform on a resource. This beginner-friendly guide explains each method with real-world analogies and practical examples.

Table of Contents

  1. What Are HTTP Methods?
  2. GET - Retrieve Data
  3. POST - Create New Data
  4. PUT - Update/Replace Data
  5. PATCH - Partial Update
  6. DELETE - Remove Data
  7. Other HTTP Methods
  8. Method Comparison

What Are HTTP Methods?

HTTP methods are like verbs in a sentence - they tell the server what action you want to take. When you visit a website or use an app, your device sends HTTP requests with specific methods.

The Main HTTP Methods

methodactionexamplechanges
GETRead/RetrieveView a webpageNo
POSTCreateSubmit a formYes
PUTUpdate/ReplaceUpdate profileYes
PATCHPartial UpdateChange emailYes
DELETERemoveDelete accountYes

Important Properties

Safe: Doesn't change anything on the server (read-only)
Idempotent: Same result if called once or multiple times
Cacheable: Response can be stored for future use

             SAFE?  IDEMPOTENT?  CACHEABLE?
GET          ✅ Yes  ✅ Yes       ✅ Yes
POST         ❌ No   ❌ No        🟡 Rarely
PUT          ❌ No   ✅ Yes       ❌ No
PATCH        ❌ No   ❌ No        ❌ No
DELETE       ❌ No   ✅ Yes       ❌ No

GET - Retrieve Data

Purpose: Read or retrieve data from the server. Never modifies anything.

Real-World Analogies

  • 📖 Reading a book in a library (don't take it home)
  • 👀 Looking at a menu (doesn't order food)
  • 🔍 Searching Google (just viewing results)
  • 📺 Watching a YouTube video (just viewing)

When to Use GET

✅ Viewing a webpage
✅ Loading user profile data
✅ Searching for products
✅ Getting a list of items
✅ Downloading a file
✅ Checking status

Basic GET Request

// Simple GET request
fetch('https://api.example.com/users/123')
  .then(response => response.json())
  .then(user => console.log(user));

// Output:
// {
//   "id": 123,
//   "name": "John Doe",
//   "email": "john@example.com"
// }

GET with Query Parameters

// Search for users with filters
fetch('https://api.example.com/users?role=admin&country=US&limit=10')
  .then(response => response.json())
  .then(users => console.log(users));

// The URL breaks down as:
// Base: https://api.example.com/users
// Parameters: ?role=admin&country=US&limit=10

GET in HTML

<!-- Every link is a GET request -->
<a href="/about">About Us</a>

<!-- Images are GET requests -->
<img src="/logo.png" alt="Logo">

<!-- Stylesheets are GET requests -->
<link rel="stylesheet" href="/styles.css">

<!-- Scripts are GET requests -->
<script src="/app.js"></script>

<!-- Forms with GET (don't use for sensitive data!) -->
<form action="/search" method="GET">
  <input type="text" name="q" placeholder="Search...">
  <button>Search</button>
</form>
<!-- Submits to: /search?q=your+search+term -->

GET Best Practices

// ✅ GOOD - Use GET for reading data
fetch('/api/users/123')

// ✅ GOOD - Use query parameters for filters
fetch('/api/products?category=electronics&maxPrice=1000')

// ❌ BAD - Don't send sensitive data in URL
fetch('/api/login?password=secret123')  // Password visible in URL!

// ❌ BAD - Don't use GET to modify data
fetch('/api/users/123/delete')  // Should use DELETE method

POST - Create New Data

Purpose: Create a new resource on the server. Sends data in the request body.

Real-World Analogies

  • ✍️ Filling out a signup form
  • 📝 Writing a new blog post
  • 💳 Placing an order
  • 📤 Uploading a photo
  • 💬 Posting a comment

When to Use POST

✅ Creating a new user account
✅ Submitting a contact form
✅ Posting a comment
✅ Uploading a file
✅ Placing an order
✅ Logging in (sending credentials)

Basic POST Request

// Create a new user
fetch('https://api.example.com/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Jane Smith',
    email: 'jane@example.com',
    password: 'securepass123'
  })
})
.then(response => response.json())
.then(newUser => console.log('Created:', newUser));

// Response (201 Created):
// {
//   "id": 124,
//   "name": "Jane Smith",
//   "email": "jane@example.com",
//   "createdAt": "2025-01-15T10:30:00Z"
// }

POST with Form Data

// Upload a file with form data
const formData = new FormData();
formData.append('name', 'Profile Picture');
formData.append('file', fileInput.files[0]);

fetch('https://api.example.com/upload', {
  method: 'POST',
  body: formData  // Don't set Content-Type - browser does it
})
.then(response => response.json())
.then(result => console.log('Uploaded:', result));

POST in HTML Forms

<!-- Traditional form POST -->
<form action="/api/contact" method="POST">
  <input type="text" name="name" placeholder="Your name" required>
  <input type="email" name="email" placeholder="Email" required>
  <textarea name="message" placeholder="Message" required></textarea>
  <button type="submit">Send</button>
</form>

<!-- File upload form -->
<form action="/api/upload" method="POST" enctype="multipart/form-data">
  <input type="file" name="avatar" accept="image/*">
  <button type="submit">Upload</button>
</form>

POST Best Practices

// ✅ GOOD - Use POST to create resources
fetch('/api/users', {
  method: 'POST',
  body: JSON.stringify({ name: 'John' })
})

// ✅ GOOD - Use POST for sensitive data (login)
fetch('/api/login', {
  method: 'POST',
  body: JSON.stringify({ email, password })
})

// ✅ GOOD - Set proper Content-Type
headers: {
  'Content-Type': 'application/json'
}

// ❌ BAD - Don't use POST to retrieve data
fetch('/api/users/123', { method: 'POST' })  // Should use GET

PUT - Update/Replace Data

Purpose: Update an entire resource, replacing all fields. If the resource doesn't exist, it may create it.

Real-World Analogies

  • 📝 Rewriting an entire document from scratch
  • 🏠 Replacing an entire house (not just renovating)
  • 📋 Overwriting a file completely
  • 🎨 Replacing a painting with a new one

When to Use PUT

✅ Updating all fields of a user profile
✅ Replacing entire configuration
✅ Overwriting a document
✅ Updating complete settings

Basic PUT Request

// Update user - replaces ALL fields
fetch('https://api.example.com/users/123', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer your-token'
  },
  body: JSON.stringify({
    name: 'John Updated',
    email: 'john.new@example.com',
    bio: 'Updated bio',
    location: 'New York'
  })
})
.then(response => response.json())
.then(user => console.log('Updated:', user));

// Important: All fields must be included!
// Any field not included will be removed or set to null

PUT vs POST Example

// POST - Create new resource (URL doesn't include ID)
POST /api/users
Body: { name: "John", email: "john@example.com" }
Result: Creates user with ID 123

// PUT - Update existing resource (URL includes ID)
PUT /api/users/123
Body: { name: "John Updated", email: "john.new@example.com" }
Result: Updates user 123 completely

Idempotent Nature of PUT

// PUT is idempotent - calling it multiple times has same result

// Call 1:
PUT /api/users/123
Body: { name: "John", email: "john@example.com" }
Result: User 123 = { name: "John", email: "john@example.com" }

// Call 2: (exact same request)
PUT /api/users/123
Body: { name: "John", email: "john@example.com" }
Result: User 123 = { name: "John", email: "john@example.com" } (same!)

// No duplicate users created, same end result

PUT Best Practices

// ✅ GOOD - Send complete object
fetch('/api/users/123', {
  method: 'PUT',
  body: JSON.stringify({
    name: 'John',
    email: 'john@example.com',
    bio: 'Developer',
    location: 'NYC'
  })
})

// ❌ BAD - Missing fields (they'll be deleted!)
fetch('/api/users/123', {
  method: 'PUT',
  body: JSON.stringify({
    email: 'john@example.com'  // Where's name, bio, location?
  })
})
// Result: User loses name, bio, and location!

// 💡 BETTER - Use PATCH for partial updates
fetch('/api/users/123', {
  method: 'PATCH',
  body: JSON.stringify({
    email: 'john@example.com'  // Only update email
  })
})

PATCH - Partial Update

Purpose: Update only specific fields of a resource without replacing the entire thing.

Real-World Analogies

  • 🔧 Fixing a typo in a document (not rewriting it)
  • 🏠 Renovating one room (not rebuilding the house)
  • 🎨 Touching up part of a painting
  • ✏️ Editing just one section of a book

When to Use PATCH

✅ Updating just the email address
✅ Changing only the password
✅ Toggling a single setting
✅ Updating specific fields
✅ Incrementing a counter

Basic PATCH Request

// Update only the email (keep everything else)
fetch('https://api.example.com/users/123', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer your-token'
  },
  body: JSON.stringify({
    email: 'john.new@example.com'
  })
})
.then(response => response.json())
.then(user => console.log('Patched:', user));

// Response:
// {
//   "id": 123,
//   "name": "John Doe",  ← Unchanged
//   "email": "john.new@example.com",  ← Updated
//   "bio": "Developer",  ← Unchanged
//   "location": "NYC"  ← Unchanged
// }

PUT vs PATCH Comparison

// Original user:
{
  "id": 123,
  "name": "John Doe",
  "email": "john@example.com",
  "bio": "Developer",
  "location": "NYC"
}

// ========================================
// Using PUT - Must send ALL fields
// ========================================

PUT /api/users/123
Body: {
  "name": "John Doe",
  "email": "john.new@example.com",  // Changed
  "bio": "Developer",
  "location": "NYC"
}

Result: Email updated ✅, but had to send everything

// ========================================
// Using PATCH - Send only what changed
// ========================================

PATCH /api/users/123
Body: {
  "email": "john.new@example.com"  // Only this
}

Result: Email updated ✅, cleaner code!

Multiple Field Updates

// Update multiple fields at once
fetch('https://api.example.com/users/123', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer your-token'
  },
  body: JSON.stringify({
    bio: 'Senior Developer',
    location: 'San Francisco'
  })
})

// Only bio and location change, name and email stay the same

Common PATCH Use Cases

// Toggle a setting
PATCH /api/users/123
Body: { emailNotifications: false }

// Increment a counter
PATCH /api/posts/456
Body: { views: { $increment: 1 } }

// Add to a list
PATCH /api/users/123
Body: { interests: { $push: "photography" } }

// Change password
PATCH /api/users/123
Body: { password: "newSecurePassword123" }

// Update last login time
PATCH /api/users/123
Body: { lastLoginAt: "2025-01-15T10:30:00Z" }

DELETE - Remove Data

Purpose: Delete a resource from the server permanently.

Real-World Analogies

  • 🗑️ Deleting a file from your computer
  • 📚 Removing a book from the library
  • 🛒 Removing an item from shopping cart
  • 👤 Deleting your account
  • 💬 Deleting a comment

When to Use DELETE

✅ Deleting a user account
✅ Removing a post or comment
✅ Clearing shopping cart
✅ Unsubscribing from a service
✅ Removing a file

Basic DELETE Request

// Delete a user
fetch('https://api.example.com/users/123', {
  method: 'DELETE',
  headers: {
    'Authorization': 'Bearer your-token'
  }
})
.then(response => {
  if (response.status === 204) {
    console.log('User deleted successfully');
  }
});

// Common responses:
// 204 No Content - Deleted, no body returned
// 200 OK - Deleted, with confirmation body
// 404 Not Found - Already deleted or doesn't exist
// 403 Forbidden - No permission to delete

DELETE with Confirmation

// Delete with confirmation in response
fetch('https://api.example.com/posts/456', {
  method: 'DELETE',
  headers: {
    'Authorization': 'Bearer your-token'
  }
})
.then(response => response.json())
.then(result => console.log(result));

// Response (200 OK):
// {
//   "message": "Post deleted successfully",
//   "deletedId": 456,
//   "deletedAt": "2025-01-15T10:30:00Z"
// }

Soft Delete vs Hard Delete

// HARD DELETE - Permanently removes from database
DELETE /api/users/123User completely removed from database

// SOFT DELETE - Marks as deleted but keeps data
PATCH /api/users/123
Body: { deleted: true, deletedAt: "2025-01-15T10:30:00Z" }
→ User still in database but marked as deleted

// Why soft delete?
// - Can recover deleted data
// - Keep records for compliance
// - Maintain referential integrity
// - Analyze deletion patterns

Delete All vs Delete One

// Delete specific item (common)
DELETE /api/users/123Deletes user 123

// Delete with filter (less common, use carefully!)
DELETE /api/posts?author=123Deletes all posts by author 123

// Bulk delete (usually POST with list)
POST /api/users/bulk-delete
Body: { userIds: [123, 124, 125] }
→ Safer for multiple deletions

DELETE Best Practices

// ✅ GOOD - Require authentication
headers: {
  'Authorization': 'Bearer your-token'
}

// ✅ GOOD - Confirm before deletion
if (confirm('Are you sure you want to delete your account?')) {
  fetch('/api/users/123', { method: 'DELETE' });
}

// ✅ GOOD - Handle errors gracefully
try {
  const response = await fetch('/api/users/123', { method: 'DELETE' });
  if (!response.ok) throw new Error('Failed to delete');
  console.log('Deleted successfully');
} catch (error) {
  alert('Error deleting user. Please try again.');
}

// ❌ BAD - No confirmation for destructive action
fetch('/api/users/123', { method: 'DELETE' });  // Instant delete!

// ❌ BAD - Using GET to delete
fetch('/api/users/123/delete')  // Should use DELETE method

Other HTTP Methods

HEAD - Get Headers Only

Like GET but returns only headers, no body. Useful for checking if resource exists.

// Check if file exists without downloading it
fetch('https://api.example.com/large-file.zip', {
  method: 'HEAD'
})
.then(response => {
  console.log('Content-Length:', response.headers.get('Content-Length'));
  console.log('Last-Modified:', response.headers.get('Last-Modified'));
  console.log('Exists:', response.ok);
});

// Use cases:
// - Check file size before downloading
// - Verify resource exists
// - Check last modified date
// - Check if URL is valid

OPTIONS - Get Available Methods

Returns which HTTP methods are allowed for a resource.

// Find out what methods are supported
fetch('https://api.example.com/users/123', {
  method: 'OPTIONS'
})
.then(response => {
  console.log('Allowed:', response.headers.get('Allow'));
});

// Response:
// Allow: GET, POST, PUT, PATCH, DELETE, OPTIONS

// Mainly used for:
// - CORS preflight requests (automatic)
// - API discovery
// - Checking permissions

CONNECT, TRACE - Rarely Used

CONNECT: Establishes a tunnel (used for HTTPS proxies)
TRACE: Echoes request back (mostly disabled for security)

These are rarely used in typical web development:

CONNECT - Used by proxies for SSL tunneling
TRACE - Debugging tool (usually disabled)

You'll likely never need these in normal API development.

Method Comparison

Complete Comparison Table

Method   Purpose          Safe?  Idempotent?  Has Body?  Use Case
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GET      Read             ✅     ✅           ❌         View page/data
POST     Create           ❌     ❌           ✅         Submit form
PUT      Replace all      ❌     ✅           ✅         Update profile
PATCH    Update partial   ❌     ❌           ✅         Change email
DELETE   Remove           ❌     ✅           ❌         Delete account
HEAD     Get headers      ✅     ✅           ❌         Check if exists
OPTIONS  Get methods      ✅     ✅           ❌         CORS preflight

Decision Tree: Which Method to Use?

Are you READING data?
└─ YES → Use GET
└─ NO ↓

Are you CREATING something new?
└─ YES → Use POST
└─ NO ↓

Are you DELETING something?
└─ YES → Use DELETE
└─ NO ↓

Are you UPDATING existing data?
├─ Updating ALL fields? → Use PUT
└─ Updating SOME fields? → Use PATCH

Common Patterns

// CRUD Operations (Create, Read, Update, Delete)

// CREATE - POST
POST   /api/users          → Create new user

// READ - GET
GET    /api/users          → List all users
GET    /api/users/123Get user 123

// UPDATE - PUT or PATCH
PUT    /api/users/123Replace user 123
PATCH  /api/users/123Update user 123 partially

// DELETE - DELETE
DELETE /api/users/123Delete user 123

Real-World Example: Blog Application

// Blog Posts API

// View all posts
GET /api/posts
GET /api/posts?category=tech&limit=10

// View single post
GET /api/posts/123

// Create new post
POST /api/posts
Body: { title: "My Post", content: "..." }

// Update entire post
PUT /api/posts/123
Body: { title: "Updated", content: "...", tags: [...] }

// Update post title only
PATCH /api/posts/123
Body: { title: "New Title" }

// Delete post
DELETE /api/posts/123

// Comments on a post
GET    /api/posts/123/comments      → List comments
POST   /api/posts/123/comments      → Add comment
DELETE /api/posts/123/comments/456Delete comment

Summary

HTTP methods are fundamental to how the web works. Understanding when to use each method is crucial for building and consuming APIs effectively.

Key Takeaways:

GET - Read data (safe, cacheable)
POST - Create new data (not idempotent)
PUT - Replace entire resource (idempotent)
PATCH - Update specific fields (more common than PUT)
DELETE - Remove data (idempotent)
✅ Use proper methods for semantic clarity
✅ Never use GET for sensitive data
✅ Always use HTTPS for security

Quick Rules:

  • Reading? → GET
  • Creating? → POST
  • Updating everything? → PUT
  • Updating some fields? → PATCH
  • Deleting? → DELETE