Skip to content

Commit 6597b82

Browse files
ad-mAdam Dobrawyclaude
authored
Add ANTICAPTCHA_API_KEY env var fallback for API key (#120)
Allow AnticaptchaClient to read the API key from the ANTICAPTCHA_API_KEY environment variable when client_key is not passed explicitly, reducing hard-coded secrets in source code. Co-authored-by: Adam Dobrawy <naczelnik@jawne.info.pl> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 0a79cf6 commit 6597b82

3 files changed

Lines changed: 36 additions & 2 deletions

File tree

README.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ Usage
5252
5353
To use this library do you need `Anticaptcha.com`_ API key.
5454

55+
You can pass the key explicitly or set the ``ANTICAPTCHA_API_KEY`` environment variable:
56+
57+
.. code:: python
58+
59+
# Explicit key
60+
client = AnticaptchaClient("my-api-key")
61+
62+
# Or set ANTICAPTCHA_API_KEY environment variable
63+
client = AnticaptchaClient()
64+
5565
Solve recaptcha
5666
###############
5767

python_anticaptcha/base.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import os
34
import requests
45
import time
56
import json
@@ -89,9 +90,15 @@ class AnticaptchaClient:
8990
response_timeout = 5
9091

9192
def __init__(
92-
self, client_key: str, language_pool: str = "en", host: str = "api.anti-captcha.com", use_ssl: bool = True,
93+
self, client_key: str | None = None, language_pool: str = "en", host: str = "api.anti-captcha.com", use_ssl: bool = True,
9394
) -> None:
94-
self.client_key = client_key
95+
self.client_key = client_key or os.environ.get("ANTICAPTCHA_API_KEY")
96+
if not self.client_key:
97+
raise AnticaptchaException(
98+
None,
99+
"CONFIG_ERROR",
100+
"API key required. Pass client_key or set ANTICAPTCHA_API_KEY env var.",
101+
)
95102
self.language_pool = language_pool
96103
self.base_url = "{proto}://{host}/".format(
97104
proto="https" if use_ssl else "http", host=host

tests/test_base.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from unittest.mock import patch, MagicMock
2+
import os
23
import pytest
34

45
from python_anticaptcha.base import AnticaptchaClient, Job, SLEEP_EVERY_CHECK_FINISHED
@@ -23,6 +24,22 @@ def test_language_pool(self):
2324
client = AnticaptchaClient("key123", language_pool="rn")
2425
assert client.language_pool == "rn"
2526

27+
def test_env_var_fallback(self, monkeypatch):
28+
monkeypatch.setenv("ANTICAPTCHA_API_KEY", "env-key-456")
29+
client = AnticaptchaClient()
30+
assert client.client_key == "env-key-456"
31+
32+
def test_explicit_key_over_env(self, monkeypatch):
33+
monkeypatch.setenv("ANTICAPTCHA_API_KEY", "env-key-456")
34+
client = AnticaptchaClient("explicit-key-789")
35+
assert client.client_key == "explicit-key-789"
36+
37+
def test_no_key_raises(self, monkeypatch):
38+
monkeypatch.delenv("ANTICAPTCHA_API_KEY", raising=False)
39+
with pytest.raises(AnticaptchaException) as exc_info:
40+
AnticaptchaClient()
41+
assert exc_info.value.error_code == "CONFIG_ERROR"
42+
2643

2744
class TestCheckResponse:
2845
def setup_method(self):

0 commit comments

Comments
 (0)