Skip to content

Commit a60997a

Browse files
VinciGit00claude
andcommitted
fix: send a User-Agent header on every API request
Both clients only sent SGAI-APIKEY, so requests reached the API with httpx's default User-Agent and were indistinguishable from any other httpx caller. Send `scrapegraph-py/<version> python/<pyversion>` on the pooled client and on the one-off absolute-URL requests in both the sync and async paths. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 07b7cad commit a60997a

4 files changed

Lines changed: 26 additions & 6 deletions

File tree

src/scrapegraph_py/async_client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import httpx
1212
from pydantic import BaseModel, TypeAdapter
1313

14-
from .env import env
14+
from .env import USER_AGENT, env
1515
from .schemas import (
1616
ApiResult,
1717
CrawlPagesQuery,
@@ -262,7 +262,7 @@ def __init__(self, *, api_key: str | None = None):
262262
self._http = httpx.AsyncClient(
263263
base_url=env.base_url,
264264
timeout=env.timeout,
265-
headers={"SGAI-APIKEY": self._api_key},
265+
headers={"SGAI-APIKEY": self._api_key, "User-Agent": USER_AGENT},
266266
)
267267

268268
self.crawl = AsyncCrawlResource(self)
@@ -292,7 +292,7 @@ async def _request[T](
292292
url,
293293
json=json_body,
294294
params=params,
295-
headers={"SGAI-APIKEY": self._api_key},
295+
headers={"SGAI-APIKEY": self._api_key, "User-Agent": USER_AGENT},
296296
)
297297
else:
298298
resp = await self._http.request(method, path, json=json_body, params=params)

src/scrapegraph_py/client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import httpx
1212
from pydantic import BaseModel, TypeAdapter
1313

14-
from .env import env
14+
from .env import USER_AGENT, env
1515
from .schemas import (
1616
ApiResult,
1717
CrawlPagesQuery,
@@ -262,7 +262,7 @@ def __init__(self, *, api_key: str | None = None):
262262
self._http = httpx.Client(
263263
base_url=env.base_url,
264264
timeout=env.timeout,
265-
headers={"SGAI-APIKEY": self._api_key},
265+
headers={"SGAI-APIKEY": self._api_key, "User-Agent": USER_AGENT},
266266
)
267267

268268
self.crawl = CrawlResource(self)
@@ -291,7 +291,7 @@ def _request[T](
291291
url,
292292
json=json_body,
293293
params=params,
294-
headers={"SGAI-APIKEY": self._api_key},
294+
headers={"SGAI-APIKEY": self._api_key, "User-Agent": USER_AGENT},
295295
timeout=env.timeout,
296296
)
297297
else:

src/scrapegraph_py/env.py

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

33
import os
4+
import platform
5+
from importlib.metadata import PackageNotFoundError, version
6+
7+
try:
8+
__version__ = version("scrapegraph-py")
9+
except PackageNotFoundError: # local checkout without an installed distribution
10+
__version__ = "unknown"
11+
12+
USER_AGENT = f"scrapegraph-py/{__version__} python/{platform.python_version()}"
413

514

615
class Env:

tests/test_client.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import pytest
55

66
from scrapegraph_py import (
7+
AsyncScrapeGraphAI,
78
FetchConfig,
89
HtmlFormatConfig,
910
ImagesFormatConfig,
@@ -14,6 +15,7 @@
1415
ScrapeGraphAI,
1516
ScreenshotFormatConfig,
1617
)
18+
from scrapegraph_py.env import USER_AGENT
1719

1820
API_KEY = "test-sgai-key"
1921
BASE_URL = "https://api.scrapegraphai.com/v2"
@@ -483,6 +485,15 @@ def test_explicit_api_key(self):
483485
sgai = ScrapeGraphAI(api_key="explicit-key")
484486
assert sgai._api_key == "explicit-key"
485487

488+
def test_sends_user_agent(self):
489+
sgai = ScrapeGraphAI(api_key=API_KEY)
490+
assert sgai._http.headers["User-Agent"] == USER_AGENT
491+
assert USER_AGENT.startswith("scrapegraph-py/")
492+
493+
def test_async_sends_user_agent(self):
494+
sgai = AsyncScrapeGraphAI(api_key=API_KEY)
495+
assert sgai._http.headers["User-Agent"] == USER_AGENT
496+
486497

487498
class TestCamelCaseSerialization:
488499
def test_snake_to_camel(self):

0 commit comments

Comments
 (0)