3434from .datasets import DatasetsClient
3535from .models import ScrapeResult
3636from .types import AccountInfo
37+ from .cli_credentials import read_cli_credentials
3738from http import HTTPStatus
3839from .exceptions import ValidationError , AuthenticationError , APIError
3940
@@ -68,8 +69,9 @@ class BrightDataClient:
6869 DEFAULT_WEB_UNLOCKER_ZONE = "sdk_unlocker"
6970 DEFAULT_SERP_ZONE = "sdk_serp"
7071
71- # Environment variable name for API token
72+ # Environment variable names for API token (checked in this order)
7273 TOKEN_ENV_VAR = "BRIGHTDATA_API_TOKEN"
74+ TOKEN_ENV_VAR_ALT = "BRIGHTDATA_API_KEY"
7375
7476 def __init__ (
7577 self ,
@@ -95,8 +97,10 @@ def __init__(
9597 Supports loading from .env files (requires python-dotenv package).
9698
9799 Args:
98- token: API token. If None, loads from BRIGHTDATA_API_TOKEN environment variable
99- (supports .env files via python-dotenv)
100+ token: API token. If None, loads from the BRIGHTDATA_API_TOKEN /
101+ BRIGHTDATA_API_KEY environment variables (supports .env files via
102+ python-dotenv), then falls back to the credentials stored by the
103+ Bright Data CLI (`brightdata login`)
100104 timeout: Default timeout in seconds for all requests (default: 30)
101105 web_unlocker_zone: Zone name for web unlocker (default: "sdk_unlocker")
102106 serp_zone: Zone name for SERP API (default: "sdk_serp")
@@ -129,7 +133,7 @@ def __init__(
129133 ... validate_token=True
130134 ... )
131135 """
132- self .token = self ._load_token (token )
136+ self .token , self . auth_source = self ._load_token (token )
133137 self .timeout = timeout
134138 self .web_unlocker_zone = web_unlocker_zone or self .DEFAULT_WEB_UNLOCKER_ZONE
135139 self .serp_zone = serp_zone or self .DEFAULT_SERP_ZONE
@@ -146,6 +150,7 @@ def __init__(
146150 rate_period = rate_period ,
147151 ssl_verify = ssl_verify ,
148152 ssl_ca_cert = ssl_ca_cert ,
153+ auth_source = self .auth_source ,
149154 )
150155
151156 self ._scrape_service : Optional [ScrapeService ] = None
@@ -177,17 +182,23 @@ def _ensure_initialized(self) -> None:
177182 "Use: async with BrightDataClient() as client: ..."
178183 )
179184
180- def _load_token (self , token : Optional [str ]) -> str :
185+ def _load_token (self , token : Optional [str ]) -> tuple :
181186 """
182- Load token from parameter or environment variable.
187+ Resolve the API token and record where it came from.
188+
189+ Resolution order: explicit parameter → environment variables
190+ (BRIGHTDATA_API_TOKEN, then BRIGHTDATA_API_KEY) → the credentials
191+ stored by the Bright Data CLI (`brightdata login`).
183192
184193 Fails fast with clear error message if no token found.
185194
186195 Args:
187196 token: Explicit token (takes precedence)
188197
189198 Returns:
190- Valid token string
199+ Tuple of (token, auth_source) where auth_source is "param",
200+ "env", or "cli_credentials" — reported in the User-Agent so
201+ SDK onboarding is measurable. The token itself is never logged.
191202
192203 Raises:
193204 ValidationError: If no token found
@@ -198,19 +209,25 @@ def _load_token(self, token: Optional[str]) -> str:
198209 f"Invalid token format. Token must be a string with at least 10 characters. "
199210 f"Got: { type (token ).__name__ } with length { len (str (token ))} "
200211 )
201- return token .strip ()
212+ return token .strip (), "param"
202213
203- # Try loading from environment variable
204- env_token = os .getenv (self .TOKEN_ENV_VAR )
214+ # Try loading from environment variables
215+ env_token = os .getenv (self .TOKEN_ENV_VAR ) or os . getenv ( self . TOKEN_ENV_VAR_ALT )
205216 if env_token :
206- return env_token .strip ()
217+ return env_token .strip (), "env"
218+
219+ # Fall back to the CLI's stored credentials (read-only)
220+ cli_token = read_cli_credentials ()
221+ if cli_token :
222+ return cli_token , "cli_credentials"
207223
208224 # No token found - fail fast with helpful message
209225 raise ValidationError (
210226 f"API token required but not found.\n \n "
211227 f"Provide token in one of these ways:\n "
212228 f" 1. Pass as parameter: BrightDataClient(token='your_token')\n "
213- f" 2. Set environment variable: { self .TOKEN_ENV_VAR } \n \n "
229+ f" 2. Set environment variable: { self .TOKEN_ENV_VAR } \n "
230+ f" 3. Log in with the Bright Data CLI: brightdata login\n \n "
214231 f"Get your API token from: https://brightdata.com/cp/setting/users"
215232 )
216233
0 commit comments