urltoolskit.org
URL utilities, in the browser
Say hi →

URI template expander

RFC 6570, all eight operators · :prefix and * explode · reverse-matches a URL back to its variables

The template language the GitHub API, OpenAPI links and every HAL or Hydra response speak — https://api.example.com/repos{/owner,repo}/issues{?state,labels*}. It looks like curl's {a,b} globbing and behaves nothing like it: the character after the brace is an operator that decides the prefix, the separator between values, and whether the value is escaped as a whole URI or as a single component. Paste a template and some JSON, and see exactly what it produces.

Ready.

How to use

  1. Paste the template. Every variable it declares is listed under the result with its operator and modifier, and whether you have supplied a value for it.
  2. Press Fill variables from template to get a JSON skeleton with the right shape for each one — a string for a plain variable, a list or a key/value object for an exploded one.
  3. Edit the values. Expansion runs as you type, so the URL and the character count update immediately.
  4. Switch the direction to Match to go the other way: give it a real URL and it recovers the variables the template would have used.

The eight operators

Assume var = "value", list = ["red","green"] and keys = {"a":1,"b":2}.

FormNameResultWhat it is for
{var}simplevalueA single path or query component. Reserved characters are escaped.
{+var}reservedvalueValues that are themselves URIs or paths — / and ? pass through unescaped.
{#var}fragment#valueAdds the # only when the variable is defined.
{.var}label.valueSubdomains and file extensions.
{/var}path/valuePath segments. {/list*} gives /red/green.
{;var}path-style parameter;var=valueMatrix parameters. The name is included automatically.
{?var}form query?var=valueThe first query parameter. {?keys*} gives ?a=1&b=2.
{&var}form continuation&var=valueA later query parameter, when the ? is already in the literal text.

The two modifiers

An undefined variable is not an error

RFC 6570 is explicit: a variable with no value expands to nothing, and the surrounding operator characters vanish with it. /users{/id} with no id is /users, not /users/ and not an error. That is genuinely useful — it is how optional query parameters work — and it is also how a typo in a variable name produces a URL that looks plausible and points at the wrong resource.

So the variable table marks every declared variable you have not supplied, and the status line names them. If that list is not empty and you did not intend it to be, you have found your bug.

Matching in reverse

Given /users{/name}/posts{/id} and /users/ada/posts/42, the variables can be recovered exactly: {"name":"ada","id":"42"}. That is useful for turning access logs or a router table back into structured data.

It does not always work, and where it cannot the tool says so rather than guessing. Once an expression declares several variables at once ({/owner,repo}) or explodes a list ({?labels*}), the output is ambiguous in reverse — nothing in ?a=1&b=2&c=3 says which parameters came from which variable, and /a/b/c could be two variables or three. Those expressions are skipped, listed by name in the status line, and the rest are still recovered.

FAQ

How is this different from the URL pattern expander?

Completely. URL pattern expander does curl-style globbing — {a,b} alternation and [1-100] ranges — and produces many URLs from one pattern. A URI template produces one URL from one set of variables, and the braces mean something entirely different. If you pasted a GitHub API template into a glob expander you would get nonsense; that is why both exist.

Which characters get escaped?

Every operator except + and # escapes anything outside the unreserved set A-Z a-z 0-9 - . _ ~, so a space becomes %20 and a slash becomes %2F. {+var} and {#var} additionally allow the reserved set and leave existing %XX triplets alone, which is what makes them safe for values that are already URLs.

Are the reserved operators supported?

No — =, ,, !, @ and | are reserved by the specification for future use and have no defined expansion, so a template using one is reported as an error instead of being guessed at.

Is anything uploaded?

No. Templates and variables are expanded in your browser. See the privacy note.