# Instances and defaults

Ky instances collect request defaults so you can share a transport policy while keeping
different API clients independent. Use [`ky`](https://bench-ky-56.atloria.app/p/bench-ky-56-cVfxjVA4Qg/developer/ky) directly for one-off requests, `ky.create()`
for a new set of defaults, and `ky.extend()` when a client should inherit and modify another
client.

## How the defaults compose

`create()` starts a new instance. It does not inherit defaults from the default instance or from
another client. `extend()` starts from its parent, then merges the options you provide. A function
form of `extend()` receives the parent options, so a child can derive a value such as a longer URL
prefix.

```mermaid
flowchart LR
    A["ky.create(defaults)"] --> B["base client"]
    B --> C["ky.extend(changes)"]
    C --> D["child client"]
    E["request options"] --> F["merged request"]
    B --> F
    D --> F
```

The instance exposes method shortcuts such as `get()` and `post()`. Each shortcut returns a
response promise with body methods such as `.text()` and `.json()`; the method shortcut supplies
the HTTP method while the instance supplies its defaults.

## Create a shared client

Pass an [`Options`](https://bench-ky-56.atloria.app/p/bench-ky-56-cVfxjVA4Qg/developer/ky-options) object to `create()`. The following client gives every
relative request a base URL, a path prefix, a header, and a request hook. The trailing slash on
`baseUrl` keeps page-relative paths under `/api/` when standard URL resolution applies.

```ts
import ky from 'ky';

async function main(): Promise<void> {
  const api = ky.create({
    baseUrl: 'https://api.example.com/api/',
    prefix: 'v1',
    headers: {
      accept: 'application/json',
    },
    hooks: {
      beforeRequest: [({request}) => {
        request.headers.set('x-client', 'web');
      }],
    },
    retry: 2,
    timeout: 10_000,
  });

  const response = await api.get('users/42');
  console.log(response.url);
}

main();
```

The request uses the instance's defaults and resolves to a URL under the configured base URL and
prefix. The hook runs immediately before the request is sent, and `retry` and `timeout` apply to
requests made through this instance unless a request supplies different values.

## Extend a client for a narrower API

Call `extend()` on the parent instance when a child shares the parent's policy. The function form
lets you read the parent options. This example adds `users` to the existing prefix and adds a
child-specific header without rebuilding the base client.

```ts
import ky from 'ky';

async function main(): Promise<void> {
  const api = ky.create({
    baseUrl: 'https://api.example.com/api/',
    prefix: 'v1',
    headers: {
      accept: 'application/json',
    },
  });

  const usersApi = api.extend(parentOptions => ({
    prefix: `${parentOptions.prefix}/users`,
    headers: {
      'x-resource': 'users',
    },
  }));

  const response = await usersApi.get('42');
  console.log(response.url);
}

main();
```

`usersApi` keeps the base URL and inherited `accept` header, adds the resource header, and sends
`GET /api/v1/users/42`. Calling `api.get('version')` still uses the parent prefix and does not use
the child prefix.

## Know what is merged

By default, `extend()` deep-merges options. Headers merge, search parameters accumulate, and hook
arrays append. This is useful for layering policy, but it is not a replacement operation.

| Option | Type | Default | Effect when extended |
| --- | --- | --- | --- |
| `baseUrl` | `string \| URL` | — | Resolves relative input after `prefix` is applied. An absolute input bypasses it. |
| `prefix` | `string \| URL` | — | Joins before URL resolution; a slash at the join boundary is normalized. |
| `headers` | header object | — | Merges with parent headers. |
| `hooks` | [`Hooks`](https://bench-ky-56.atloria.app/p/bench-ky-56-cVfxjVA4Qg/developer/ky-hooks) | — | Appends hook arrays by default. |
| `searchParams` | [`SearchParamsOption`](https://bench-ky-56.atloria.app/p/bench-ky-56-cVfxjVA4Qg/developer/ky) | `''` | Accumulates with the parent's search parameters. |
| `retry` | [`RetryOptions`](https://bench-ky-56.atloria.app/p/bench-ky-56-cVfxjVA4Qg/developer/ky-retryoptions) \| number | — | Supplies retry policy for requests from the instance. |
| `timeout` | `number \| false` | — | Sets the per-attempt response timeout in milliseconds. |

Use [`replaceOption`](https://bench-ky-56.atloria.app/p/bench-ky-56-cVfxjVA4Qg/developer/ky) when a child must replace a merged value rather than add to it.
For example, this child runs only its own `beforeRequest` hook:

```ts
import ky, {replaceOption} from 'ky';

async function main(): Promise<void> {
  const api = ky.create({
    hooks: {
      beforeRequest: [() => {
        console.log('parent hook');
      }],
    },
  });

  const child = api.extend({
    hooks: replaceOption({
      beforeRequest: [() => {
        console.log('child hook');
      }],
    }),
  });

  await child.get('https://example.com');
}

main();
```

The child hook replaces the parent's `beforeRequest` array. The same marker can replace other
deep-merged values, including headers, search parameters, context, and signals.

## Choose `baseUrl` or `prefix`

Use `baseUrl` in most cases. It follows standard URL resolution: an input beginning with `/`
starts at the origin root, so it can override a path in the base URL. Use `prefix` when an
origin-relative input such as `/users` must be treated as page-relative and appended to the
prefix. The prefix is joined before `baseUrl` resolves the resulting input.

For a base URL with a path, include its trailing `/` when you want `users` and `./users` to extend
that path rather than replace its last segment. A `Request` input bypasses both `baseUrl` and
`prefix`; `searchParams` still applies.

## Related

- [`Options`](https://bench-ky-56.atloria.app/p/bench-ky-56-cVfxjVA4Qg/developer/ky-options) — request and instance options.
- [`ResponsePromise`](https://bench-ky-56.atloria.app/p/bench-ky-56-cVfxjVA4Qg/developer/ky-responsepromise) — body methods returned by an instance request.
- [Shared clients and URL defaults](https://bench-ky-56.atloria.app/p/bench-ky-56-cVfxjVA4Qg/developer/shared-clients-and-url-defaults) — the warning about
  inherited headers, search parameters, and hooks.
