AnvilJSON utilities

Anvil › Docs › /v1/input-lag

Input lag API: milliseconds from button press to picture, and what would help most

Input lag is six small waits added together: the controller's next report, the trip over the cable or radio, the game noticing, the game drawing the frame, the screen's next refresh and the screen's own processing. A console on a TV with its picture extras on lands around 130 ms; the same setup with game mode and a cable is nearer 70 ms. This endpoint adds the pieces up for a setup and ranks the changes that would save the most.

In one line: GET /v1/input-lag?link=bt&rate=250&fps=60&hz=60&screen=tv returns JSON. No key, CORS on, 60 requests a minute.
GET

/v1/input-lag

Input lag: ms from button press to picture, split into six parts, with the biggest fixes ranked. Change the values and press Send request to call the live API.

Parameters

NameTypeWhat it doesDefault
modestringestimate (default) | compare | optionsestimate
examplestringStart from a preset setup: sofa, sofafix, pc, laptop—
linkstringController connection: wired, dongle (own 2.4 GHz receiver) or bt (Bluetooth)bt
rateintegerPolling rate in Hz: 125, 250, 500, 1000, 2000, 4000 or 8000250
fpsintegerGame frame rate (10-1000)60
pipestringGame setting: low (Reflex / Anti-Lag / Boost), normal or vsync (caps fps at the refresh rate)normal
hzintegerScreen refresh rate: 60, 75, 90, 120, 144, 165, 240 or 36060
screenstringmonitor, office, gametv, tv (picture extras on), projector or customtv
screen_msnumberYour screen's own processing lag in ms from a review (0-300); implies screen=custom—
b_*stringmode=compare: the same parameters prefixed b_ describe setup B (b_example, b_link, b_screen ...)—

Example

Request:

GET https://api.oddlathe.com/v1/input-lag?link=bt&rate=250&fps=60&hz=60&screen=tv

Response (generated by the real code when these docs were last built; random or time-based values will differ for you):

{
 "mode": "estimate",
 "setup": {
  "rate_hz": 250,
  "link": "bt",
  "link_name": "Bluetooth",
  "fps": 60,
  "effective_fps": 60,
  "pipe": "normal",
  "pipe_name": "Normal",
  "hz": 60,
  "screen": "tv",
  "screen_name": "TV with picture extras on (game mode off)",
  "screen_ms": 70
 },
 "typical_ms": 131,
 "best_ms": 110.3,
 "worst_ms": 151.7,
 "wobble_ms": 41.3,
 "frames_at_60": 7.9,
 "parts": [
  {
   "key": "poll",
   "name": "Waiting for the next report (polling)",
   "ms": 2
  },
  {
   "key": "link",
   "name": "The trip (cable or wireless)",
   "ms": 9
  },
  {
   "key": "wait",
   "name": "Waiting for the game to look",
   "ms": 8.3
  },
 …

Code examples

curl
curl 'https://api.oddlathe.com/v1/input-lag?link=bt&rate=250&fps=60&hz=60&screen=tv'
JavaScript (browser or Node 18+)
const params = new URLSearchParams({
  link: "bt",
  rate: "250",
  fps: "60",
  hz: "60",
  screen: "tv"
});
const res = await fetch(`https://api.oddlathe.com/v1/input-lag?${params}`);
if (!res.ok) throw new Error((await res.json()).error.message);
const data = await res.json();
console.log(data);
Python (standard library only)
import json, urllib.parse, urllib.request

params = urllib.parse.urlencode({"link": "bt", "rate": "250", "fps": "60", "hz": "60", "screen": "tv"})
url = "https://api.oddlathe.com/v1/input-lag?" + params
# Send a User-Agent: the edge network refuses Python's default one.
req = urllib.request.Request(url, headers={"User-Agent": "my-script/1.0"})
with urllib.request.urlopen(req, timeout=10) as r:
    data = json.load(r)
print(data)

When it's useful

  • Setup helpers and buying guides: show what a TV's game mode or a 1000 Hz controller really saves
  • Game launchers or companion apps that suggest the one setting worth changing
  • Comparing two setups side by side with <code>mode=compare</code>
  • Teaching why the screen, not the controller, is usually the big piece

Good to know

  • mode=estimate (default) takes link, rate, fps, pipe, hz and screen (or screen_ms from a review), or starts from example=sofa|sofafix|pc|laptop and overrides from there. Returns typical_ms, best_ms, worst_ms, frames_at_60, the six parts, the biggest part, a verdict (Excellent under 30 ms up to Sluggish at 120+) and ranked suggestions.
  • mode=compare reads setup B from the same names prefixed b_ (for example b_example=sofafix or b_screen=gametv) and returns both plus difference_ms.
  • mode=options lists every choice with its figures. Words like cable, bluetooth, reflex and gamemode are accepted as aliases; anything else that isn't on the list is a 400, never silently swapped.
  • Figures are rounded typical values, not a measurement of your hardware. V-Sync caps the game at the refresh rate and queues about a frame more.
  • Browser UI: Tooltern input lag calculator with the same model, a coloured breakdown bar and pin-to-compare (nothing leaves your device). Playful version: how a controller talks to a console.

How long it takes from pressing a button to seeing it on screen, using rounded typical figures: waiting for the next polling report, the trip over a cable or wireless, waiting for the game to read input, the game making the picture (1.5 to 3 frames), waiting for the screen's refresh and the screen's own processing. Returns typical, luckiest and unluckiest totals, frames late at 60 fps, a five-band verdict and the best single change per setting ranked by milliseconds saved. mode=compare puts two setups side by side (B uses b_ parameters) and mode=options lists every choice. Same model as the Tooltern input lag calculator. Pure maths; nothing is stored.

Errors

Errors are JSON like {"error": {"code": "…", "message": "…"}}. The ones this endpoint can return:

  • bad_param (400): a value is the wrong type or out of range (the message says which)
  • rate_limited (429): over 60 requests a minute; wait for Retry-After seconds

Questions

How much lag does a TV add?

With motion smoothing and other picture extras on, often 50 to 150 ms; in game mode about 10 to 20 ms. <code>/v1/input-lag?example=sofa</code> gives 131 ms and suggests game mode or a monitor first.

Does a 1000 Hz controller matter?

Going from 125 Hz to 1000 Hz saves about 3.5 ms on average. It shows up in the suggestions only when bigger fixes are already done.

Is Bluetooth noticeably slower than a cable?

About 8 ms more on average in this model, plus a few ms of wobble. Real, but usually smaller than V-Sync or a TV's processing.

Is anything stored?

Never. Pure maths on the query string.

Related endpoints

Prefer a page to an API?

Published · OpenAPI 3.1 spec · Limits and privacy