Web endpoint URLs

User-specified URLs

Users have partial control over the URL of a web endpoint. For the stub.webhook, stub.asgi and stub.wsgi decorators, an optional label keyword argument can be provided, which allocates the URL https://<workspace>--<label>.modal.run for your endpoint.

For example, the following code will deploy a webhook at the URL https://my-workspace--foo-bar.modal.run:

def my_f():

Auto-generated URLs

If a label is not specified, web endpoints receive a generated URL under the modal.run domain. These generated URLs contain a subdomain label that is unique to the running endpoint.

Deployed apps

Webhooks served by a deployed application have subdomains composed of the following parts:

  • Workspace name slug: ECorpecorp
  • App name slug: text_to_speechtext-to-speech
  • Function name slug: flask_appflask-app

The deployed webhook URL for this example is https://ecorp--text-to-speech-flask-app.modal.run.

This URL is reserved for the deployed application’s webhook. Running the application during development will not replace the deployed application’s association with the deployed URL.

Ephemeral apps

Webhooks run in ephemeral apps have predictable, unique subdomains, distinct from the subdomain of any associated deployment.

The subdomain of a webhook running in an ephemeral app is composed of the following parts:

  • Workspace name slug: ECorpecorp
  • App name slug: text_to_speechtext-to-speech
  • Function name slug: flask_appflask-app
  • [Optional] Member name slug, in cases where app runs in a shared workspace: erikbern
  • [Optional] An instance identifier, ensuring uniqueness in the presence of concurrent ephemeral app runs: 1234abcd
  • A -dev suffix, calling out that this webhook is not deployed.

Combining the example parts, the ephemeral webhook’s URL could be https://ecorp--text-to-speech-flask-app-erikbern-1234abcd-dev.modal.run.

The components of an ephemeral webhook subdomain ensure URL predictability during development and testing, in both personal and shared workspaces. Multiple copies of a webhook can be active when a Modal app is run in two or more terminal windows, or when multiple developers are iterating on the same application codebase. Every copy will be uniquely addressable while running.


If an emphemeral webhook is running and another ephemeral webhook is created seeking the same webhook label, the new webhook function will steal the running webhook’s label.

This ensures the latest iteration of an ephemeral webhook function is serving requests, while older ones stop recieving web traffic.

(Previously concurrently running ephemeral app webhooks would include conflict-avoiding hashes.)


If a generated subdomain label is longer than 63 characters, it will be truncated.

For example, the following subdomain label is too long, 67 characters: ecorp--text-to-speech-really-really-long-function-name-erikbern-dev.

The truncation happens by calculating a SHA-256 hash of the overlong label, then taking the first 6 characters of this hash. The overlong subdomain label is truncated to 56 characters, and then joined by a dash to the hash prefix.

The combination of the label hashing and truncation provides a unique list of 63 characters, complying with both DNS system limits and uniqueness requirements.