OPTIONS Method

Fundamentals Jan 9, 2026 HTTP
http methods rest cors

Definition

OPTIONS is an HTTP method that requests information about the communication options available for a resource or server. It returns which HTTP methods are supported (GET, POST, PUT, DELETE, etc.) and other capabilities without performing any action on the resource itself. OPTIONS is a safe method - it doesn’t modify server state.

The primary use of OPTIONS is CORS preflight requests: when a browser makes a cross-origin request with custom headers or methods other than GET/POST, it first sends an OPTIONS request to check if the actual request is allowed. The server responds with CORS headers indicating what’s permitted.

OPTIONS is essential for API discoverability and CORS security. It helps clients understand what operations they can perform on a resource before attempting them, and browsers use it automatically to enforce same-origin policy exceptions.

Example

Discover Allowed Methods:

OPTIONS /api/users/123 HTTP/1.1
Host: api.example.com

// Response shows allowed methods
HTTP/1.1 200 OK
Allow: GET, PUT, PATCH, DELETE, OPTIONS

CORS Preflight - Before PUT Request:

OPTIONS /api/posts/456 HTTP/1.1
Origin: https://myapp.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type, Authorization

// Server responds with CORS headers
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400

Server-Wide Capabilities:

OPTIONS * HTTP/1.1
Host: api.example.com

// Response shows server capabilities
HTTP/1.1 200 OK
Allow: GET, POST, OPTIONS

Analogy

Restaurant Menu Inquiry: Before ordering, you ask “What dishes do you serve? What cooking methods do you use?” OPTIONS is like asking a restaurant what they can make before you place your order. They tell you their capabilities without cooking anything.

Phone Call Screening: Think of OPTIONS like when you call a business and an automated system tells you “Press 1 for sales, 2 for support, 3 for billing.” It’s telling you what operations are available before you choose one.

Permission Check: Like asking a bouncer “Can I bring my friend? Can we wear sneakers?” before entering a club. The bouncer tells you the rules (OPTIONS response) without actually letting you in yet.

Code Example

// OPTIONS - Discover resource capabilities
OPTIONS /api/users/789 HTTP/1.1
Host: api.example.com

// Response - Allowed methods
HTTP/1.1 200 OK
Allow: GET, PUT, PATCH, DELETE, OPTIONS
Content-Type: application/json
Content-Length: 0

// OPTIONS - CORS preflight (browser automatic)
OPTIONS /api/posts HTTP/1.1
Host: api.example.com
Origin: https://myapp.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type, X-Custom-Header

// Response - CORS headers
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://myapp.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, X-Custom-Header, Authorization
Access-Control-Max-Age: 86400
Access-Control-Allow-Credentials: true
Vary: Origin

// After successful preflight, browser sends actual request:
POST /api/posts HTTP/1.1
Host: api.example.com
Origin: https://myapp.example.com
Content-Type: application/json
X-Custom-Header: value

{"title": "New Post", "content": "..."}

// OPTIONS - Server-wide capabilities
OPTIONS * HTTP/1.1
Host: api.example.com

// Response
HTTP/1.1 200 OK
Allow: GET, HEAD, POST, OPTIONS
Server: nginx/1.25.0
Content-Length: 0

// OPTIONS - API documentation endpoint
OPTIONS /api/products HTTP/1.1
Host: api.example.com
Accept: application/json

// Response - Detailed capabilities
HTTP/1.1 200 OK
Allow: GET, POST, OPTIONS
Content-Type: application/json

{
  "methods": {
    "GET": {
      "description": "List all products",
      "parameters": ["page", "limit", "category"],
      "authentication": false
    },
    "POST": {
      "description": "Create new product",
      "authentication": true,
      "requiredRole": "admin",
      "contentType": "application/json"
    }
  },
  "endpoints": [
    "/api/products",
    "/api/products/{id}"
  ]
}

// OPTIONS - CORS preflight rejection
OPTIONS /api/admin/users HTTP/1.1
Origin: https://untrusted.com
Access-Control-Request-Method: DELETE

// Response - CORS blocked
HTTP/1.1 403 Forbidden
Content-Type: application/json

{
  "error": "cors_not_allowed",
  "message": "Origin not permitted"
}

// OPTIONS - Method not allowed
OPTIONS /api/readonly-resource HTTP/1.1

// Response
HTTP/1.1 200 OK
Allow: GET, HEAD, OPTIONS

Diagram

sequenceDiagram
    participant Browser
    participant Server
    participant Backend

    Note over Browser: User triggers cross-origin POST

    Browser->>Server: OPTIONS /api/posts (preflight)
    Note over Browser,Server: Check CORS permissions

    Server->>Backend: Check CORS policy
    Backend-->>Server: Policy rules

    Server-->>Browser: 204 No Content + CORS headers
    Note over Server,Browser: Access-Control-Allow-*

    Note over Browser: Preflight passed!

    Browser->>Server: POST /api/posts (actual request)
    Note over Browser,Server: With custom headers

    Server->>Backend: Process POST request
    Backend-->>Server: Created resource

    Server-->>Browser: 201 Created
    Note over Server,Browser: Actual response

    Note over Browser: Alternative: Preflight Failed

    Browser->>Server: OPTIONS /api/admin (preflight)
    Server-->>Browser: 403 Forbidden
    Note over Browser: Browser blocks actual request
    Note over Browser: Error in console

Best Practices

  1. Implement for all resources: Support OPTIONS on every endpoint
  2. Return 200 OK or 204 No Content: Standard successful responses
  3. Include Allow header: List supported HTTP methods
  4. Handle CORS preflight: Respond with Access-Control-* headers
  5. Cache preflight responses: Use Access-Control-Max-Age header
  6. Keep it lightweight: OPTIONS should be fast, no heavy computation
  7. Document capabilities: Optionally return detailed API info in body
  8. Support asterisk: OPTIONS * for server-wide capabilities
  9. No authentication required: OPTIONS should work without auth
  10. Validate origin: Check Origin header for CORS security

Common Mistakes

Not implementing OPTIONS at all, causing CORS failures. Requiring authentication for OPTIONS requests (breaks CORS preflight). Returning 405 Method Not Allowed instead of implementing OPTIONS. Not including Allow header in response. Forgetting Access-Control-Allow-Headers in CORS preflight response. Setting Access-Control-Max-Age too low, causing excessive preflight requests. Not handling wildcard OPTIONS * for server capabilities. Including response body when 204 No Content should be used. Not varying response by Origin header (cache issues). Hardcoding allowed methods instead of dynamically determining them. Not supporting OPTIONS for all endpoints consistently.

Standards & RFCs