How HTTP Works

Cookie attribute

< Set-Cookie: id=a3fWa; Path=/

Path

Learn how the Path cookie attribute restricts which URL paths can receive cookies. Understand path matching rules and how to scope cookies to specific routes.

Reviewed 5 min readbeginner3 sourcesTry itMarkdown
Default if omitted
Directory of the request URL's path
Accepts
A URL path prefix
Sent back to server
No: never echoed in the Cookie header
Spec
RFC 6265 §4.1.2.4, RFC 6265bis (draft)
On this page

TL;DR: Restricts which URL paths receive the cookie (e.g., Path=/admin only sends to admin pages) - use to scope cookies to specific app sections and reduce unnecessary cookie transmission.

What is the Path Attribute?

The Path attribute controls which URL paths can receive a cookie. It’s like setting delivery instructions for mail - “only deliver to apartments on the 3rd floor.” Without this attribute, cookies are sent to all paths on the domain, which can be inefficient and potentially insecure.

This attribute helps scope cookies to specific sections of your application.

How It Works

No Path Attribute (Default)

Cookie sent to all paths on the domain:

Set-Cookie: userData=john123
# From: /shop/cart
# Sent to: /, /shop, /shop/cart, /admin, /api, etc.

With Path Attribute

Cookie only sent to matching paths:

Set-Cookie: adminToken=xyz789; Path=/admin
# From: /admin/dashboard
# Sent to: /admin, /admin/dashboard, /admin/users
# Not sent to: /, /shop, /api

Path Matching Rules

Exact Path and Subdirectories

Set-Cookie: data=value; Path=/shop

Sent to:

  • /shop ✅
  • /shop/ ✅
  • /shop/cart ✅
  • /shop/checkout/payment ✅

Not sent to:

  • / ❌
  • /api ❌
  • /shopping ❌ (different path)
  • /admin ❌

Root Path

Set-Cookie: globalData=value; Path=/

Sent to all paths:

  • / ✅
  • /shop ✅
  • /admin ✅
  • /api/users ✅

Specific Subdirectory

Set-Cookie: apiKey=secret; Path=/api/v1

Sent to:

  • /api/v1 ✅
  • /api/v1/ ✅
  • /api/v1/users ✅
  • /api/v1/orders/123 ✅

Not sent to:

  • /api ❌
  • /api/v2 ❌
  • /shop ❌

Real-World Examples

Admin Panel Security

Restrict admin cookies to admin paths:

Set-Cookie: adminSession=secure123; Path=/admin; HttpOnly; Secure; Max-Age=3600

Admin cookies never sent to public pages, reducing exposure.

API Authentication

Scope API tokens to API endpoints:

Set-Cookie: apiToken=bearer456; Path=/api; HttpOnly; Secure; SameSite=Strict

Shopping Cart

Keep cart data in shopping section:

Set-Cookie: cartId=cart789; Path=/shop; Max-Age=604800; SameSite=Lax

User Dashboard

Personal data only in user area:

Set-Cookie: userPrefs=theme:dark; Path=/dashboard; Max-Age=2592000

Multi-Tenant Applications

Separate tenant data by path:

Set-Cookie: tenantId=acme; Path=/tenants/acme; Secure
Set-Cookie: tenantId=corp; Path=/tenants/corp; Secure

Development vs Production APIs

# Development API
Set-Cookie: devToken=dev123; Path=/dev/api; Max-Age=86400

# Production API
Set-Cookie: prodToken=prod456; Path=/api; Max-Age=3600

Security Benefits

Principle of Least Privilege

Only send cookies where needed:

# ❌ Overly broad: Admin token sent everywhere
Set-Cookie: adminToken=secret; HttpOnly; Secure

# ✅ Properly scoped: Admin token only in admin area
Set-Cookie: adminToken=secret; Path=/admin; HttpOnly; Secure

Reduced Attack Surface

# Admin cookie not exposed to public pages
Set-Cookie: adminSession=xyz; Path=/admin; HttpOnly; Secure

# Public pages can't access admin cookies
# Reduces risk if public pages have XSS vulnerabilities

Data Isolation

# Different user types get different cookies
Set-Cookie: customerData=abc; Path=/customer; HttpOnly
Set-Cookie: employeeData=def; Path=/employee; HttpOnly
Set-Cookie: adminData=ghi; Path=/admin; HttpOnly

Implementation Examples

Express.js

// Admin routes
app.use('/admin', (req, res, next) => {
  // Admin-specific cookie
  res.cookie('adminContext', 'true', {
    path: '/admin',
    httpOnly: true,
    secure: true,
    maxAge: 2 * 60 * 60 * 1000 // 2 hours
  })
  next()
})

// API routes
app.use('/api', (req, res, next) => {
  // API-specific cookie
  res.cookie('apiVersion', 'v2', {
    path: '/api',
    maxAge: 24 * 60 * 60 * 1000 // 24 hours
  })
  next()
})

// Shopping cart
app.post('/shop/add-to-cart', (req, res) => {
  res.cookie('cartId', generateCartId(), {
    path: '/shop',
    maxAge: 7 * 24 * 60 * 60 * 1000, // 1 week
    sameSite: 'lax'
  })
})

Python Flask

@app.route('/admin/login', methods=['POST'])
def admin_login():
    session_id = generate_admin_session()

    response = make_response({'success': True})
    response.set_cookie(
        'adminSession',
        session_id,
        path='/admin',
        httponly=True,
        secure=True,
        max_age=7200  # 2 hours
    )

    return response

PHP

// Admin area cookie
if (strpos($_SERVER['REQUEST_URI'], '/admin') === 0) {
    setcookie('adminToken', $token, [
        'expires' => time() + 3600,
        'path' => '/admin',
        'secure' => true,
        'httponly' => true,
        'samesite' => 'Strict'
    ]);
}

Getting Path right

1. Use specific paths for sensitive cookies:

✅ Set-Cookie: adminToken=secret; Path=/admin; HttpOnly; Secure
❌ Set-Cookie: adminToken=secret; HttpOnly; Secure

2. Match cookie path to application structure:

/api/v1     → Path=/api/v1
/admin      → Path=/admin
/user       → Path=/user
/shop       → Path=/shop

3. Use root path sparingly:

# Only for truly global data
Set-Cookie: siteTheme=dark; Path=/; Max-Age=31536000

# Not for sensitive data
❌ Set-Cookie: sessionId=secret; Path=/
✅ Set-Cookie: sessionId=secret; Path=/app; HttpOnly

4. Consider cookie cleanup:

// Clear cookies from specific paths
app.post('/logout', (req, res) => {
  // Clear admin cookies
  res.clearCookie('adminSession', { path: '/admin' })

  // Clear user cookies
  res.clearCookie('userSession', { path: '/user' })

  // Clear global cookies
  res.clearCookie('globalPrefs', { path: '/' })
})

5. Document path strategy:

// Cookie path strategy:
// /admin/* - Admin-only cookies (sessions, permissions)
// /api/*   - API-specific cookies (tokens, rate limits)
// /shop/*  - Shopping-related cookies (cart, preferences)
// /*       - Global cookies (theme, language)

const COOKIE_PATHS = {
  ADMIN: '/admin',
  API: '/api',
  SHOP: '/shop',
  GLOBAL: '/'
}

Common Patterns

Hierarchical Permissions

// Different access levels with different paths
const setUserCookie = (level, sessionId) => {
  const paths = {
    admin: '/admin',
    manager: '/manager',
    user: '/user',
    public: '/'
  }

  res.cookie('sessionId', sessionId, {
    path: paths[level],
    httpOnly: true,
    secure: true
  })
}

API Versioning

// Different cookies for different API versions
app.use('/api/v1', (req, res, next) => {
  res.cookie('apiVersion', 'v1', { path: '/api/v1' })
  next()
})

app.use('/api/v2', (req, res, next) => {
  res.cookie('apiVersion', 'v2', { path: '/api/v2' })
  next()
})

Feature Flags by Section

// Different features enabled in different sections
const featureFlags = {
  '/beta': { newUI: true, advancedFeatures: true },
  '/stable': { newUI: false, advancedFeatures: false }
}

app.use('/beta', (req, res, next) => {
  res.cookie('features', JSON.stringify(featureFlags['/beta']), {
    path: '/beta'
  })
  next()
})

Troubleshooting

// Problem: Path doesn't match request URL
Set-Cookie: data=value; Path=/admin
// Request to: /shop/cart (no match)

// Solution: Check path matching
console.log('Request path:', req.path)
console.log('Cookie path:', '/admin')
console.log('Matches:', req.path.startsWith('/admin'))
// Problem: No path restriction
Set-Cookie: adminToken=secret  // Sent everywhere!

// Solution: Add appropriate path
Set-Cookie: adminToken=secret; Path=/admin

Path Case Sensitivity

// Problem: Case mismatch
Set-Cookie: data=value; Path=/Admin
// Request to: /admin (lowercase)

// Solution: Use consistent casing (usually lowercase)
Set-Cookie: data=value; Path=/admin
  • Domain - Controls domain access
  • Secure - HTTPS-only transmission
  • HttpOnly - Prevent JavaScript access
  • SameSite - Cross-site request control

Frequently asked questions

What is the Path cookie attribute?

Path restricts which URL paths receive the cookie. A cookie with Path=/admin is only sent to URLs starting with /admin. Default is the current path.

How does Path matching work?

Path uses prefix matching. Path=/docs matches /docs, /docs/api, /docs/guide. It does not match /documents because that is a different prefix.

Should I always set Path?

Set Path=/ for site-wide cookies. Use specific paths only when you need to restrict cookie scope, like admin-only cookies with Path=/admin.

Is Path a security feature?

No, Path is not a security boundary. JavaScript on any path can read cookies for other paths on the same origin. Use it for organization, not security.

Sources

  1. MDN Web Docs: Cookie Pathdeveloper.mozilla.org
  2. RFC 6265: Path Attributerfc-editor.org
  3. RFC 6265bis (draft): current cookie behavior (SameSite, prefixes, 400-day cap)datatracker.ietf.org

Keep going

Browse /search