New: see the walk between your classes on the timetable

Build with the data

Status and limits

How much you can ask for, what the error codes mean, and what to expect when something is slow or down.

Rate limits#

There is no key, so limits are per network address. Many students share one address on campus Wi-Fi, so the numbers are generous. They are there to stop floods, not to ration normal use.

SurfaceLimitWhen you pass it
Module API, /api/modules/{code}About 60 requests a minute from one address, counted per Cloudflare location. Cached responses do not count.429 with Retry-After
Data files, /data/api/*No fixed limit. They are static files cached for a day, so download each one once.Heavy use may be blocked
MCP server, /mcp3,000 requests a minute from one address. A body over 16 KB is refused, and results are capped at 100 modules or 200 exams.429 with Retry-After

The MCP server's limits, in order of checks, are on the MCP limits and errors page.

Status codes#

CodeMeaning
200Success.
308The module URL was not canonical. Follow the Location header, or send an uppercase code and no query string.
400The module code is not letters and digits, 2 to 12 characters.
404No such module, or no such semester file. The error body names what was missing.
429Too many requests. Wait the number of seconds in Retry-After, then try again.
503The service is temporarily unavailable or switched off. Wait the seconds in Retry-After. Do not retry in a tight loop.
403, 405, 413, 415MCP only: a browser on another site, a method other than POST, a body over 16 KB, or a body that is not JSON.

Caching and CORS#

  • Module API responses are cached for an hour in the browser and up to a week at the edge. Data files are cached for a day.
  • The module API and the data files send Access-Control-Allow-Origin: *, so JavaScript on any site can read them. The MCP server does not, and refuses browsers on other sites.
  • Unknown module codes are cached too, so a repeated miss is cheap for you and for the server.
  • How current the data itself is, is on the data freshness page.

When to retry#

  • Retry only 429 and 503, and wait the seconds in Retry-After first.
  • If a retry fails again, wait longer each time, and stop after a few tries.
  • Do not retry 400 or 404. Fix the request.
  • Send requests one at a time or in small groups. For many modules, download modules.json instead.

Availability#

NTUMods is built and run by one person, and it is free. There is no uptime promise, no support contract and no status page. Under the terms of use, any API or dataset can change or go away without notice, so build in a fallback for the day it does.

If something looks broken, wait a minute and try again. If it stays broken, tell me through the feedback page or open an issue on GitHub.

Found something wrong?

NTUMods is built and maintained by one person, so a short note goes a long way. Pick what fits, add the details, and I will look at it.

I'll use this to follow up with you.

Attaches your saved timetables and settings to help debug the issue. On by default, turn off to exclude it.

Developer? Open an issue or PR.