[API reference](https://evolu.dev/docs/api-reference) › [@evolu/common](https://evolu.dev/docs/api-reference/common) › [Type](https://evolu.dev/docs/api-reference/common/Type) › Url

```ts
const Url: brand(
  "Url",
  String,
  (value: string) =>
    canonicalizeUrl(value) === value
      ? ok()
      : err<UrlError>({ type: "Url", value }),
  formatUrlError,
);
```

Defined in: [packages/common/src/Type.ts:9709](https://github.com/evoluhq/evolu/blob/aa223771feea747ffb1b0f5f3271574455633e37/packages/common/src/Type.ts#L9709)

Canonical absolute URL [String](https://evolu.dev/docs/api-reference/common/Type/variables/String).

A Url is a URL as the [WHATWG URL Standard](https://url.spec.whatwg.org/)
serializes it, so `new URL(value).href` equals the value, such as
`https://example.com/` for `https://example.com`. Like [DateIso](https://evolu.dev/docs/api-reference/common/Type/variables/DateIso), it has
one spelling per URL on an engine, so equal URLs are equal strings there. Url
does not normalize; use [UrlFromString](https://evolu.dev/docs/api-reference/common/Type/variables/UrlFromString) to convert other spellings, such
as user input. Relative URLs are rejected.

Url accepts any scheme, including `javascript:`, whose links run code when
followed. Use [HttpUrl](https://evolu.dev/docs/api-reference/common/Type/variables/HttpUrl) for links. Url sets no maximum length, and a
`data:` URL can hold a whole file; compose `maxLength(2048)(Url)` or another
limit when one matters, such as for a database column.

Url validates with the platform's `URL`, which browsers and Node.js provide,
and which Expo SDK 58 and later installs on React Native. React Native
without Expo has its own `URL`, which accepts strings that are not URLs, so
install one that follows the standard, such as
[whatwg-url-minimum](https://github.com/expo/whatwg-url-minimum) 0.2 or
later, which Expo installs, as the [react-native
example](https://github.com/evoluhq/evolu/blob/main/examples/react-native/polyfills.ts)
does without replacing React Native's `URL.createObjectURL`.

Engines don't always parse a URL the same way. Chromium percent-encodes `|`
in a path, which the others keep, and accepts a space in a host, which they
reject. Firefox rejects some `xn--` hosts that the others accept, and
whatwg-url-minimum accepts some right-to-left hosts that the others reject.
Revisions of the standard change the serialization too, as when it began to
percent-encode `^` in a path in 2025. No engine decodes a percent-escape, so
the same URL can be two different strings, and a Url from one device can fail
validation on another device or after an engine update. Evolu does not
validate the values other devices write, so where a valid Url matters,
transform a value read from the database with UrlFromString and handle its
error. It doesn't make another engine's spelling equal to this one's.

### Example

```ts
import { assertErr, assertOk, Url } from "@evolu/common";

assertOk(Url.fromUnknown("https://example.com/"), "https://example.com/");

assertErr(Url.fromUnknown("https://example.com"), {
  type: "Url",
  value: "https://example.com",
});
```