# Engines and proxy tiers

> Leave them empty. We start on the cheapest route and climb only when a site blocks us.

**TL;DR**: leave `engine` and `proxy_tier` out. We start on the cheapest
route and move up only when the site blocks us. Set them only when an answer
tells you to.

## The routes

A route is one engine on one kind of exit IP. We call each one a rung.

| Rung | Engine | Exit | `X-Route` |
| -- | -- | -- | -- |
| `h:dc` | HTTP | datacenter | `http/datacenter` |
| `h:res` | HTTP | residential | `http/residential` |
| `c:dc` | the browser (Chrome) | datacenter | `browser/datacenter` |
| `c:res` | the browser (Chrome) | residential | `browser/residential` |

The HTTP engine sends one request that looks like a real Chrome or Firefox
on the wire. `X-Identity` says which. The browser is a real Chrome that runs
the page's JavaScript. [Credits and pricing](/guides/credits) has the price of
each route.

## The climb

With `engine` and `proxy_tier` left out:

1. We fetch over HTTP on a datacenter exit, the cheapest route.
2. When the site blocks us, we try the next route your plan allows.
3. A try that ended in a block we detected costs nothing.

`X-Hops` lists every try, in order, with its time, as a JSON array:
`[{"rung":"h:dc","identity":"chrome","ms":412,"outcome":"blocked"},{"rung":"c:dc","identity":"chrome","ms":2900,"outcome":"ok"}]`.
`outcome` says how each try ended: `ok`, `blocked`, `needs_js`, or the error code of a try that failed.
When an answer is blocked, `X-Untried` lists the routes we
did not try yet.

## When to set them yourself

- **`X-Hint: needs_js`.** The page builds itself with JavaScript, and HTTP
  got only the empty shell. The answer is free. Send `engine=browser`.
- **`X-Hint: browser_blocked`.** The site blocks our browser too. The answer
  is a free 422 `blocked`.
- **The browser on residential IPs.** Send `engine=browser` and
  `proxy_tier=residential`. We never pick this route on our own.
- **One visitor across requests.** Send the same `session_id` on each. A
  session uses a residential exit unless you send `proxy_tier=datacenter`.

The browser takes GET only, with no `session_id` and no `identity`. Any of
them with `engine=browser` is a free 400 `bad_parameter` that names the one
to drop.

## Ask first

`GET /v1/tier?host=` lists, under `capabilities`, the routes that can serve
you right now. [Check a site first](/guides/credits#check-a-site-first) shows how.
