# Quickstart

> Get an API key and send your first request in about two minutes, with examples in cURL, Python, Node.js and Go.

This guide creates a text captcha job and fetches the answer. You need a Solvecha account, an API key and a picture of a text captcha saved as `captcha.png`.


1. **Create an account and copy your key.** [Register](https://solvecha.com/register), then open the [dashboard](https://solvecha.com/dashboard). Your key starts with `slv_`.
2. **Confirm your e-mail address.** The free tier starts as soon as it is confirmed: 100 successful solves per UTC day, no card. Need more? Top up a balance ($0.10 per 1,000 solves) or pick a monthly plan in the [dashboard](https://solvecha.com/dashboard). See [Plans and billing](https://solvecha.com/docs/plans-and-billing.md).
3. **Send a request.** The base URL is `https://api.solvecha.com`. Send your key in the `Authorization` header.
4. **Fetch the answer.** The first response only holds a job id. Ask for the answer about once per second.


## Your first request

This request creates a job:


**cURL**

```bash
KEY=YOUR_API_KEY
IMG=$(base64 -w0 captcha.png)

curl -X POST "https://api.solvecha.com/v1/recognition/textcaptcha" \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d "{\"image_data\": [\"$IMG\"]}"

# {"data": "1234567"}
```

**Python**

```python
import base64
import requests

headers = {"Authorization": "Bearer YOUR_API_KEY"}
with open("captcha.png", "rb") as f:
    image = base64.b64encode(f.read()).decode()

job = requests.post(
    "https://api.solvecha.com/v1/recognition/textcaptcha",
    headers=headers,
    json={"image_data": [image]},
).json()
print(job)  # {"data": "1234567"}
```

**Node.js**

```js
import { readFile } from "node:fs/promises";

const headers = { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" };
const image = (await readFile("captcha.png")).toString("base64");

const job = await fetch("https://api.solvecha.com/v1/recognition/textcaptcha", {
  method: "POST",
  headers,
  body: JSON.stringify({ image_data: [image] }),
}).then((r) => r.json());
console.log(job); // { data: "1234567" }
```

**Go**

```go
package main

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"strings"
)

func main() {
	raw, err := os.ReadFile("captcha.png")
	if err != nil {
		panic(err)
	}
	payload, _ := json.Marshal(map[string]any{"image_data": []string{base64.StdEncoding.EncodeToString(raw)}})

	req, _ := http.NewRequest("POST", "https://api.solvecha.com/v1/recognition/textcaptcha", strings.NewReader(string(payload)))
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	req.Header.Set("Content-Type", "application/json")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	var job struct {
		Data string `json:"data"`
	}
	_ = json.NewDecoder(resp.Body).Decode(&job)
	fmt.Println(job.Data) // 1234567
}
```


## Fetch the answer

Send a `GET` request to the same type path with the job id. While the job runs, you get HTTP status `409` and error `14`. Try again after one second.


**cURL**

```bash
curl "https://api.solvecha.com/v1/recognition/textcaptcha?id=1234567" \
  -H "Authorization: Bearer YOUR_API_KEY"

# {"data": ["K7m2Q"]}
```

**Python**

```python
import time

for _ in range(30):
    time.sleep(1)
    r = requests.get(
        "https://api.solvecha.com/v1/recognition/textcaptcha",
        headers=headers,
        params={"id": job["data"]},
    )
    if r.status_code == 409:  # error 14: not ready yet
        continue
    r.raise_for_status()
    print(r.json()["data"])  # ["K7m2Q"]
    break
```

**Node.js**

```js
for (let i = 0; i < 30; i++) {
  await new Promise((resolve) => setTimeout(resolve, 1000));
  const res = await fetch(`https://api.solvecha.com/v1/recognition/textcaptcha?id=${job.data}`, { headers });
  if (res.status === 409) continue; // error 14: not ready yet
  console.log((await res.json()).data); // ["K7m2Q"]
  break;
}
```

**Go**

```go
for i := 0; i < 30; i++ {
	time.Sleep(time.Second)
	req, _ := http.NewRequest("GET", "https://api.solvecha.com/v1/recognition/textcaptcha?id="+job.Data, nil)
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	body, _ := io.ReadAll(resp.Body)
	resp.Body.Close()
	if resp.StatusCode == 409 { // error 14: not ready yet
		continue
	}
	fmt.Println(string(body)) // {"data":["K7m2Q"]}
	break
}
```


For the Go loop, add `io` and `time` to the imports.


> **Note:**
> Keep your key on your server. Do not put it in a web page that other people can open.



> **Tip:**
> Does your script run a real browser? Use [CloakBrowser](https://solvecha.com/docs/cloakbrowser.md) so that fewer captchas appear, and let the [Solvecha extension](https://solvecha.com/docs/browser-extension.md) solve the ones that do.


## Next steps


- [Authentication](https://solvecha.com/docs/authentication.md): All the ways to send your key.
- [Captcha types](https://solvecha.com/docs/captcha-types/recaptcha.md): What to send and what you get back for each type.
- [Best practices](https://solvecha.com/docs/best-practices.md): Retries, proxies, rate limits and feedback.
- [Errors](https://solvecha.com/docs/errors.md): Every error code and what to do.
