Standard embeddings — x-ratelimit-limit meters input texts, not requests; documented 512-text batch unreachable at Tier 1

Pre-flight checklist

  • This is about the Perplexity API, not the Perplexity app, Comet, or web UI.
  • I have removed API keys, secrets, and private data.
  • I have included enough information for someone else to reproduce the issue.

Bug type

  • Error response or failed request
  • Incorrect or unexpected model output
  • Missing, invalid, or stale citations/search results
  • Streaming issue
  • Structured output or JSON schema issue
  • SDK issue
  • Billing, credits, or rate limit issue
  • Dashboard, API key, or auth issue
  • Other API bug

Affected API area

  • Agent API
  • Search API
  • Sonar API
  • Embeddings API
  • SDKs
  • Dashboard, API keys, or auth
  • Billing or credits
  • Not sure

Summary

The Tier 1 QPS limit is being treated as a texts limit. Unable to send up to 512 texts per request, any texts past 167 in a second fail.

Expected behavior

Able to send up to 167/QPS with each query/call having up to 512 texts to be embedded. These are short texts of 270 tokens or less.

Actual behavior

Response body on failure:

{“error”:{“message”:“Rate limit exceeded, please try again later.”,“type”:“request_rate_limit_exceeded”,“code”:429}}

The core observation. x-ratelimit-limit is 167, and a single request consumes one unit per input text rather than one unit per request:

  • 1 request of 3 texts → x-ratelimit-used: 3
  • 1 request of 100 texts → x-ratelimit-used: 100
  • 1 request of 167 texts → x-ratelimit-used: 167, remaining: 0

Twenty simultaneous 50-text requests produced exactly three successes, with x-ratelimit-used reading 50, 100 and 150; the fourth would have reached 200 and was refused. Ten simultaneous 100-text requests produced one success. Under a requests-per-second model these should have been 20/20 and 10/10.

Consequently any request whose text count exceeds 167 is refused regardless of client idle time (tested to 40 s), which makes the documented maximum unreachable on this account:

┌─────────┬────────┐
│ n texts │ Result │
├─────────┼────────┤
│ 167 │ 200 │
├─────────┼────────┤
│ 168 │ 429 │
├─────────┼────────┤
│ 200 │ 429 │
├─────────┼────────┤
│ 256 │ 429 │
├─────────┼────────┤
│ 400 │ 429 │
├─────────┼────────┤
│ 512 │ 429 │
└─────────┴────────┘

Minimal reproduction

Confirmed — reproduces on the first call after 45 s idle. Twelve lines, no dependencies beyond requests:


import os, requests

r = requests.post(
    "https://api.perplexity.ai/v1/embeddings",
    headers={"Authorization": f"Bearer {os.environ['PERPLEXITY_API_KEY']}"},
    json={"model": "pplx-embed-v1-4b",
          "input": [f"text number {i}" for i in range(200)]},
)
print(r.status_code)
print(r.text)


Control: change range(200) to range(167) and the identical script returns 200 with 167 embeddings. That single-character difference is the whole bug.

Response or error

HTTP/1.1 429

CF-RAY: a310919b3fb133a6-EWR
Connection: keep-alive
Content-Length: 116
Content-Type: application/json
Date: Wed, 26 Aug 2026 05:52:09 GMT
Server: cloudflare
Strict-Transport-Security: max-age=15552000; includeSubDomains; preload
access-control-allow-origin: *
cf-cache-status: DYNAMIC
set-cookie: __cf_bm=<redacted>; __cflb=<redacted>
x-request-id: 1fac928d-2a12-48f0-827a-731348ee4772

{"error":{"message":"Rate limit exceeded, please try again later.","type":"request_rate_limit_exceeded","code":429}}

That's the complete header set — no x-ratelimit-limit, -remaining, -used or -reset at all, which is the detail worth their attention.

Request details

  • Endpoint: POST https://api.perplexity.ai/v1/embeddings
  • Model or preset: pplx-embed-v1-4b
  • SDK/language/version: Python 3.12, requests 2.34.2 (also reproduced with httpx 0.28 sync and async — not SDK-specific)
  • Request ID: 62bdcf5c-f86a-4a3c-a28e-6943b1ac582a
  • Approximate time and timezone: (UTC): 05:48:48
  • Consistent or intermittent: Consistent

Additional context