screenshotscout 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- screenshotscout-0.1.0/.gitignore +24 -0
- screenshotscout-0.1.0/LICENSE +21 -0
- screenshotscout-0.1.0/PKG-INFO +314 -0
- screenshotscout-0.1.0/README.md +284 -0
- screenshotscout-0.1.0/examples/README.md +16 -0
- screenshotscout-0.1.0/examples/async_client.py +22 -0
- screenshotscout-0.1.0/examples/binary_capture.py +30 -0
- screenshotscout-0.1.0/examples/capture_url.py +21 -0
- screenshotscout-0.1.0/examples/json_capture.py +26 -0
- screenshotscout-0.1.0/pyproject.toml +87 -0
- screenshotscout-0.1.0/src/screenshotscout/__init__.py +57 -0
- screenshotscout-0.1.0/src/screenshotscout/_response.py +185 -0
- screenshotscout-0.1.0/src/screenshotscout/_serialization.py +213 -0
- screenshotscout-0.1.0/src/screenshotscout/client.py +459 -0
- screenshotscout-0.1.0/src/screenshotscout/errors.py +83 -0
- screenshotscout-0.1.0/src/screenshotscout/models.py +252 -0
- screenshotscout-0.1.0/src/screenshotscout/py.typed +1 -0
- screenshotscout-0.1.0/tests/test_async_client.py +200 -0
- screenshotscout-0.1.0/tests/test_client.py +776 -0
- screenshotscout-0.1.0/tests/test_package.py +4 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
|
|
5
|
+
.venv/
|
|
6
|
+
venv/
|
|
7
|
+
|
|
8
|
+
build/
|
|
9
|
+
dist/
|
|
10
|
+
*.egg-info/
|
|
11
|
+
|
|
12
|
+
.coverage
|
|
13
|
+
coverage.xml
|
|
14
|
+
htmlcov/
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
.mypy_cache/
|
|
17
|
+
.ruff_cache/
|
|
18
|
+
.tox/
|
|
19
|
+
.nox/
|
|
20
|
+
|
|
21
|
+
.env
|
|
22
|
+
.env.*
|
|
23
|
+
.DS_Store
|
|
24
|
+
Thumbs.db
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Oleksii Velykyi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: screenshotscout
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official Python SDK for the Screenshot Scout screenshot API.
|
|
5
|
+
Project-URL: Homepage, https://screenshotscout.com
|
|
6
|
+
Project-URL: Repository, https://github.com/screenshotscout/screenshotscout-python
|
|
7
|
+
Project-URL: Issues, https://github.com/screenshotscout/screenshotscout-python/issues
|
|
8
|
+
Author: Oleksii Velykyi
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: screenshot,screenshot-api,screenshotscout,sdk,url-to-image,webpage-screenshot,website-screenshot
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Requires-Dist: httpx<1,>=0.28.1
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: build<2,>=1.5; extra == 'dev'
|
|
25
|
+
Requires-Dist: mypy<3,>=2.3; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest-asyncio<2,>=1.4; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest<10,>=9.1; extra == 'dev'
|
|
28
|
+
Requires-Dist: ruff<1,>=0.15; extra == 'dev'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# Screenshot Scout Python SDK
|
|
32
|
+
|
|
33
|
+
The official Python SDK for the [Screenshot Scout](https://screenshotscout.com/) screenshot API.
|
|
34
|
+
Easily capture website screenshots from your Python applications.
|
|
35
|
+
|
|
36
|
+
## Requirements
|
|
37
|
+
|
|
38
|
+
Python 3.11 or newer.
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```shell
|
|
43
|
+
python -m pip install screenshotscout
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Get your API credentials
|
|
47
|
+
|
|
48
|
+
Before using the SDK, [sign up for Screenshot Scout](https://screenshotscout.com/auth/signup) or sign in to
|
|
49
|
+
your existing account. Screenshot Scout automatically creates a default API key when you sign up.
|
|
50
|
+
|
|
51
|
+
Open the [API Keys page](https://screenshotscout.com/app/api-keys), copy the access key and secret
|
|
52
|
+
key, and store them securely. The access key is required when creating `ScreenshotScoutClient` or
|
|
53
|
+
`AsyncScreenshotScoutClient`. The secret key is optional and enables
|
|
54
|
+
[signed requests](#signed-requests).
|
|
55
|
+
|
|
56
|
+
## Capture a screenshot
|
|
57
|
+
|
|
58
|
+
Read your access key from an environment variable and pass it to the client:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
import os
|
|
62
|
+
from pathlib import Path
|
|
63
|
+
|
|
64
|
+
from screenshotscout import (
|
|
65
|
+
BinaryCaptureResponse,
|
|
66
|
+
CaptureFormat,
|
|
67
|
+
CaptureOptions,
|
|
68
|
+
ScreenshotScoutClient,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
access_key = os.environ.get("SCREENSHOTSCOUT_ACCESS_KEY")
|
|
72
|
+
if not access_key:
|
|
73
|
+
raise RuntimeError("Set SCREENSHOTSCOUT_ACCESS_KEY first.")
|
|
74
|
+
|
|
75
|
+
with ScreenshotScoutClient(access_key) as client:
|
|
76
|
+
response = client.capture(
|
|
77
|
+
"https://example.com",
|
|
78
|
+
CaptureOptions(format=CaptureFormat.WEBP, full_page=True),
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
if not isinstance(response, BinaryCaptureResponse):
|
|
82
|
+
raise RuntimeError("Expected a binary capture response")
|
|
83
|
+
|
|
84
|
+
Path("screenshot.webp").write_bytes(response.bytes)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
POST is used by default. The screenshot is available as `response.bytes`.
|
|
88
|
+
|
|
89
|
+
## Request a JSON result
|
|
90
|
+
|
|
91
|
+
Set `response_type` to `CaptureResponseType.JSON` to receive screenshot metadata instead of the
|
|
92
|
+
binary file:
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
import os
|
|
96
|
+
|
|
97
|
+
from screenshotscout import (
|
|
98
|
+
CaptureOptions,
|
|
99
|
+
CaptureResponseType,
|
|
100
|
+
JsonCaptureResponse,
|
|
101
|
+
ScreenshotScoutClient,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
options = CaptureOptions(response_type=CaptureResponseType.JSON)
|
|
105
|
+
|
|
106
|
+
with ScreenshotScoutClient(os.environ["SCREENSHOTSCOUT_ACCESS_KEY"]) as client:
|
|
107
|
+
response = client.capture("https://example.com", options)
|
|
108
|
+
|
|
109
|
+
if not isinstance(response, JsonCaptureResponse):
|
|
110
|
+
raise RuntimeError("Expected a JSON capture response")
|
|
111
|
+
|
|
112
|
+
print(response.result.screenshot_url)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Async client
|
|
116
|
+
|
|
117
|
+
Use `AsyncScreenshotScoutClient` in applications that use `asyncio`. `await capture()` waits for
|
|
118
|
+
and returns the completed capture; it does not create a background job.
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
import asyncio
|
|
122
|
+
import os
|
|
123
|
+
|
|
124
|
+
from screenshotscout import AsyncScreenshotScoutClient, BinaryCaptureResponse, CaptureOptions
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
async def main() -> None:
|
|
128
|
+
async with AsyncScreenshotScoutClient(os.environ["SCREENSHOTSCOUT_ACCESS_KEY"]) as client:
|
|
129
|
+
response = await client.capture(
|
|
130
|
+
"https://example.com",
|
|
131
|
+
CaptureOptions(full_page=True),
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
if isinstance(response, BinaryCaptureResponse):
|
|
135
|
+
print(len(response.bytes))
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
asyncio.run(main())
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Use GET
|
|
142
|
+
|
|
143
|
+
POST is the default. Pass `CaptureHTTPMethod.GET` when you need a GET request:
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
from screenshotscout import CaptureHTTPMethod
|
|
147
|
+
|
|
148
|
+
response = client.capture(
|
|
149
|
+
"https://example.com",
|
|
150
|
+
method=CaptureHTTPMethod.GET,
|
|
151
|
+
)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Build a capture URL
|
|
155
|
+
|
|
156
|
+
Use `build_capture_url()` when a browser, an HTML `<img>` element, or another application needs to
|
|
157
|
+
load the screenshot directly. Building the URL does not make a request.
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
from screenshotscout import CaptureOptions
|
|
161
|
+
|
|
162
|
+
capture_url = client.build_capture_url(
|
|
163
|
+
"https://example.com",
|
|
164
|
+
CaptureOptions(full_page=True, block_ads=True),
|
|
165
|
+
)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The generated URL contains your access key. If the client has a secret key, the URL is signed
|
|
169
|
+
automatically; otherwise, it is unsigned. Treat generated URLs as sensitive. Before exposing one
|
|
170
|
+
to a browser or user, add your secret key to the client and enable **Require signed requests** on
|
|
171
|
+
the [API Keys page](https://screenshotscout.com/app/api-keys).
|
|
172
|
+
|
|
173
|
+
## Signed requests
|
|
174
|
+
|
|
175
|
+
Pass your secret key to sign GET and POST requests and generated capture URLs automatically. The
|
|
176
|
+
secret key stays in your application and is never transmitted.
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
import os
|
|
180
|
+
|
|
181
|
+
from screenshotscout import ScreenshotScoutClient
|
|
182
|
+
|
|
183
|
+
with ScreenshotScoutClient(
|
|
184
|
+
os.environ["SCREENSHOTSCOUT_ACCESS_KEY"],
|
|
185
|
+
secret_key=os.environ["SCREENSHOTSCOUT_SECRET_KEY"],
|
|
186
|
+
) as client:
|
|
187
|
+
response = client.capture("https://example.com")
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
See the [signed requests guide](https://screenshotscout.com/docs/signed-requests) for details.
|
|
191
|
+
|
|
192
|
+
## Capture options
|
|
193
|
+
|
|
194
|
+
The target URL is the first argument to `capture()`. Use `CaptureOptions` keyword arguments to
|
|
195
|
+
customize the screenshot:
|
|
196
|
+
|
|
197
|
+
| Area | `CaptureOptions` fields |
|
|
198
|
+
|---|---|
|
|
199
|
+
| Output | `format`, `response_type` |
|
|
200
|
+
| Network and location | `country`, `proxy`, `geolocation_latitude`, `geolocation_longitude`, `geolocation_accuracy` |
|
|
201
|
+
| Cookies and headers | `cookies`, `headers` |
|
|
202
|
+
| Navigation and timing | `timeout`, `wait_until`, `navigation_timeout`, `delay` |
|
|
203
|
+
| Device emulation | `device`, `device_viewport_width`, `device_viewport_height`, `device_scale_factor`, `device_is_mobile`, `device_has_touch`, `device_user_agent` |
|
|
204
|
+
| Page preferences | `timezone`, `media_type`, `color_scheme`, `reduced_motion` |
|
|
205
|
+
| Full page | `full_page`, `full_page_pre_scroll`, `full_page_pre_scroll_step`, `full_page_pre_scroll_step_delay`, `full_page_max_height` |
|
|
206
|
+
| Blocking | `block_cookie_banners`, `block_ads`, `block_chat_widgets` |
|
|
207
|
+
| Interactions and injection | `hide_selectors`, `click_selectors`, `click_all_selectors`, `inject_css`, `inject_js`, `bypass_csp` |
|
|
208
|
+
| Selection and clipping | `selector`, `clip_x`, `clip_y`, `clip_width`, `clip_height` |
|
|
209
|
+
| Image output | `image_width`, `image_height`, `image_mode`, `image_anchor`, `image_allow_upscale`, `image_background`, `image_quality` |
|
|
210
|
+
| PDF output | `pdf_paper_format`, `pdf_landscape`, `pdf_print_background`, `pdf_margin`, `pdf_margin_top`, `pdf_margin_right`, `pdf_margin_bottom`, `pdf_margin_left`, `pdf_scale` |
|
|
211
|
+
| Caching | `cache`, `cache_ttl`, `cache_key` |
|
|
212
|
+
| Storage | `storage_mode`, `storage_endpoint`, `storage_bucket`, `storage_region`, `storage_object_key` |
|
|
213
|
+
|
|
214
|
+
Use the provided constants for autocomplete, or pass a string:
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
from screenshotscout import CaptureFormat, CaptureOptions, CaptureWaitUntil
|
|
218
|
+
|
|
219
|
+
options = CaptureOptions(
|
|
220
|
+
format=CaptureFormat.WEBP,
|
|
221
|
+
wait_until=CaptureWaitUntil.LOAD,
|
|
222
|
+
)
|
|
223
|
+
response = client.capture("https://example.com", options)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
See the [screenshot option reference](https://screenshotscout.com/docs/screenshot-options) for
|
|
227
|
+
available values and examples.
|
|
228
|
+
|
|
229
|
+
## Timeouts
|
|
230
|
+
|
|
231
|
+
```python
|
|
232
|
+
import os
|
|
233
|
+
|
|
234
|
+
from screenshotscout import CaptureOptions, ScreenshotScoutClient
|
|
235
|
+
|
|
236
|
+
with ScreenshotScoutClient(
|
|
237
|
+
os.environ["SCREENSHOTSCOUT_ACCESS_KEY"],
|
|
238
|
+
request_timeout=300.0,
|
|
239
|
+
) as client:
|
|
240
|
+
response = client.capture(
|
|
241
|
+
"https://example.com",
|
|
242
|
+
CaptureOptions(timeout=180),
|
|
243
|
+
)
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
`CaptureOptions.timeout` controls how long Screenshot Scout may spend capturing the page.
|
|
247
|
+
`request_timeout` controls how long your application waits for the API response.
|
|
248
|
+
|
|
249
|
+
## Responses
|
|
250
|
+
|
|
251
|
+
- `BinaryCaptureResponse` provides the screenshot as `bytes`, along with URL, expiry, and cache
|
|
252
|
+
information when available.
|
|
253
|
+
- `JsonCaptureResponse` provides screenshot metadata in `result`.
|
|
254
|
+
|
|
255
|
+
Both response types include `raw_response` for access to the HTTP status, headers, content type,
|
|
256
|
+
and body.
|
|
257
|
+
|
|
258
|
+
## Error handling
|
|
259
|
+
|
|
260
|
+
```python
|
|
261
|
+
import os
|
|
262
|
+
|
|
263
|
+
from screenshotscout import (
|
|
264
|
+
ScreenshotScoutAPIError,
|
|
265
|
+
ScreenshotScoutClient,
|
|
266
|
+
ScreenshotScoutError,
|
|
267
|
+
ScreenshotScoutTransportError,
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
try:
|
|
271
|
+
with ScreenshotScoutClient(os.environ["SCREENSHOTSCOUT_ACCESS_KEY"]) as client:
|
|
272
|
+
response = client.capture("https://example.com")
|
|
273
|
+
except ScreenshotScoutAPIError as error:
|
|
274
|
+
print(error.status, error.error_code, error.error_message)
|
|
275
|
+
except ScreenshotScoutTransportError as error:
|
|
276
|
+
print(error.cause)
|
|
277
|
+
except ScreenshotScoutError as error:
|
|
278
|
+
print(error)
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
The SDK does not automatically retry failed requests.
|
|
282
|
+
|
|
283
|
+
## Examples
|
|
284
|
+
|
|
285
|
+
Runnable programs are available in [`examples`](examples):
|
|
286
|
+
|
|
287
|
+
- [`binary_capture.py`](examples/binary_capture.py)
|
|
288
|
+
- [`json_capture.py`](examples/json_capture.py)
|
|
289
|
+
- [`async_client.py`](examples/async_client.py)
|
|
290
|
+
- [`capture_url.py`](examples/capture_url.py)
|
|
291
|
+
|
|
292
|
+
## Development
|
|
293
|
+
|
|
294
|
+
Create a virtual environment and install the package with its development tools:
|
|
295
|
+
|
|
296
|
+
```shell
|
|
297
|
+
python -m venv .venv
|
|
298
|
+
python -m pip install --upgrade pip
|
|
299
|
+
python -m pip install -e ".[dev]"
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Run the local checks:
|
|
303
|
+
|
|
304
|
+
```shell
|
|
305
|
+
python -m ruff format --check .
|
|
306
|
+
python -m ruff check .
|
|
307
|
+
python -m mypy
|
|
308
|
+
python -m pytest
|
|
309
|
+
python -m build
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## License
|
|
313
|
+
|
|
314
|
+
This project is licensed under the MIT License. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# Screenshot Scout Python SDK
|
|
2
|
+
|
|
3
|
+
The official Python SDK for the [Screenshot Scout](https://screenshotscout.com/) screenshot API.
|
|
4
|
+
Easily capture website screenshots from your Python applications.
|
|
5
|
+
|
|
6
|
+
## Requirements
|
|
7
|
+
|
|
8
|
+
Python 3.11 or newer.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```shell
|
|
13
|
+
python -m pip install screenshotscout
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Get your API credentials
|
|
17
|
+
|
|
18
|
+
Before using the SDK, [sign up for Screenshot Scout](https://screenshotscout.com/auth/signup) or sign in to
|
|
19
|
+
your existing account. Screenshot Scout automatically creates a default API key when you sign up.
|
|
20
|
+
|
|
21
|
+
Open the [API Keys page](https://screenshotscout.com/app/api-keys), copy the access key and secret
|
|
22
|
+
key, and store them securely. The access key is required when creating `ScreenshotScoutClient` or
|
|
23
|
+
`AsyncScreenshotScoutClient`. The secret key is optional and enables
|
|
24
|
+
[signed requests](#signed-requests).
|
|
25
|
+
|
|
26
|
+
## Capture a screenshot
|
|
27
|
+
|
|
28
|
+
Read your access key from an environment variable and pass it to the client:
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
import os
|
|
32
|
+
from pathlib import Path
|
|
33
|
+
|
|
34
|
+
from screenshotscout import (
|
|
35
|
+
BinaryCaptureResponse,
|
|
36
|
+
CaptureFormat,
|
|
37
|
+
CaptureOptions,
|
|
38
|
+
ScreenshotScoutClient,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
access_key = os.environ.get("SCREENSHOTSCOUT_ACCESS_KEY")
|
|
42
|
+
if not access_key:
|
|
43
|
+
raise RuntimeError("Set SCREENSHOTSCOUT_ACCESS_KEY first.")
|
|
44
|
+
|
|
45
|
+
with ScreenshotScoutClient(access_key) as client:
|
|
46
|
+
response = client.capture(
|
|
47
|
+
"https://example.com",
|
|
48
|
+
CaptureOptions(format=CaptureFormat.WEBP, full_page=True),
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
if not isinstance(response, BinaryCaptureResponse):
|
|
52
|
+
raise RuntimeError("Expected a binary capture response")
|
|
53
|
+
|
|
54
|
+
Path("screenshot.webp").write_bytes(response.bytes)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
POST is used by default. The screenshot is available as `response.bytes`.
|
|
58
|
+
|
|
59
|
+
## Request a JSON result
|
|
60
|
+
|
|
61
|
+
Set `response_type` to `CaptureResponseType.JSON` to receive screenshot metadata instead of the
|
|
62
|
+
binary file:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
import os
|
|
66
|
+
|
|
67
|
+
from screenshotscout import (
|
|
68
|
+
CaptureOptions,
|
|
69
|
+
CaptureResponseType,
|
|
70
|
+
JsonCaptureResponse,
|
|
71
|
+
ScreenshotScoutClient,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
options = CaptureOptions(response_type=CaptureResponseType.JSON)
|
|
75
|
+
|
|
76
|
+
with ScreenshotScoutClient(os.environ["SCREENSHOTSCOUT_ACCESS_KEY"]) as client:
|
|
77
|
+
response = client.capture("https://example.com", options)
|
|
78
|
+
|
|
79
|
+
if not isinstance(response, JsonCaptureResponse):
|
|
80
|
+
raise RuntimeError("Expected a JSON capture response")
|
|
81
|
+
|
|
82
|
+
print(response.result.screenshot_url)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Async client
|
|
86
|
+
|
|
87
|
+
Use `AsyncScreenshotScoutClient` in applications that use `asyncio`. `await capture()` waits for
|
|
88
|
+
and returns the completed capture; it does not create a background job.
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
import asyncio
|
|
92
|
+
import os
|
|
93
|
+
|
|
94
|
+
from screenshotscout import AsyncScreenshotScoutClient, BinaryCaptureResponse, CaptureOptions
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
async def main() -> None:
|
|
98
|
+
async with AsyncScreenshotScoutClient(os.environ["SCREENSHOTSCOUT_ACCESS_KEY"]) as client:
|
|
99
|
+
response = await client.capture(
|
|
100
|
+
"https://example.com",
|
|
101
|
+
CaptureOptions(full_page=True),
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
if isinstance(response, BinaryCaptureResponse):
|
|
105
|
+
print(len(response.bytes))
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
asyncio.run(main())
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Use GET
|
|
112
|
+
|
|
113
|
+
POST is the default. Pass `CaptureHTTPMethod.GET` when you need a GET request:
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
from screenshotscout import CaptureHTTPMethod
|
|
117
|
+
|
|
118
|
+
response = client.capture(
|
|
119
|
+
"https://example.com",
|
|
120
|
+
method=CaptureHTTPMethod.GET,
|
|
121
|
+
)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Build a capture URL
|
|
125
|
+
|
|
126
|
+
Use `build_capture_url()` when a browser, an HTML `<img>` element, or another application needs to
|
|
127
|
+
load the screenshot directly. Building the URL does not make a request.
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from screenshotscout import CaptureOptions
|
|
131
|
+
|
|
132
|
+
capture_url = client.build_capture_url(
|
|
133
|
+
"https://example.com",
|
|
134
|
+
CaptureOptions(full_page=True, block_ads=True),
|
|
135
|
+
)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The generated URL contains your access key. If the client has a secret key, the URL is signed
|
|
139
|
+
automatically; otherwise, it is unsigned. Treat generated URLs as sensitive. Before exposing one
|
|
140
|
+
to a browser or user, add your secret key to the client and enable **Require signed requests** on
|
|
141
|
+
the [API Keys page](https://screenshotscout.com/app/api-keys).
|
|
142
|
+
|
|
143
|
+
## Signed requests
|
|
144
|
+
|
|
145
|
+
Pass your secret key to sign GET and POST requests and generated capture URLs automatically. The
|
|
146
|
+
secret key stays in your application and is never transmitted.
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
import os
|
|
150
|
+
|
|
151
|
+
from screenshotscout import ScreenshotScoutClient
|
|
152
|
+
|
|
153
|
+
with ScreenshotScoutClient(
|
|
154
|
+
os.environ["SCREENSHOTSCOUT_ACCESS_KEY"],
|
|
155
|
+
secret_key=os.environ["SCREENSHOTSCOUT_SECRET_KEY"],
|
|
156
|
+
) as client:
|
|
157
|
+
response = client.capture("https://example.com")
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
See the [signed requests guide](https://screenshotscout.com/docs/signed-requests) for details.
|
|
161
|
+
|
|
162
|
+
## Capture options
|
|
163
|
+
|
|
164
|
+
The target URL is the first argument to `capture()`. Use `CaptureOptions` keyword arguments to
|
|
165
|
+
customize the screenshot:
|
|
166
|
+
|
|
167
|
+
| Area | `CaptureOptions` fields |
|
|
168
|
+
|---|---|
|
|
169
|
+
| Output | `format`, `response_type` |
|
|
170
|
+
| Network and location | `country`, `proxy`, `geolocation_latitude`, `geolocation_longitude`, `geolocation_accuracy` |
|
|
171
|
+
| Cookies and headers | `cookies`, `headers` |
|
|
172
|
+
| Navigation and timing | `timeout`, `wait_until`, `navigation_timeout`, `delay` |
|
|
173
|
+
| Device emulation | `device`, `device_viewport_width`, `device_viewport_height`, `device_scale_factor`, `device_is_mobile`, `device_has_touch`, `device_user_agent` |
|
|
174
|
+
| Page preferences | `timezone`, `media_type`, `color_scheme`, `reduced_motion` |
|
|
175
|
+
| Full page | `full_page`, `full_page_pre_scroll`, `full_page_pre_scroll_step`, `full_page_pre_scroll_step_delay`, `full_page_max_height` |
|
|
176
|
+
| Blocking | `block_cookie_banners`, `block_ads`, `block_chat_widgets` |
|
|
177
|
+
| Interactions and injection | `hide_selectors`, `click_selectors`, `click_all_selectors`, `inject_css`, `inject_js`, `bypass_csp` |
|
|
178
|
+
| Selection and clipping | `selector`, `clip_x`, `clip_y`, `clip_width`, `clip_height` |
|
|
179
|
+
| Image output | `image_width`, `image_height`, `image_mode`, `image_anchor`, `image_allow_upscale`, `image_background`, `image_quality` |
|
|
180
|
+
| PDF output | `pdf_paper_format`, `pdf_landscape`, `pdf_print_background`, `pdf_margin`, `pdf_margin_top`, `pdf_margin_right`, `pdf_margin_bottom`, `pdf_margin_left`, `pdf_scale` |
|
|
181
|
+
| Caching | `cache`, `cache_ttl`, `cache_key` |
|
|
182
|
+
| Storage | `storage_mode`, `storage_endpoint`, `storage_bucket`, `storage_region`, `storage_object_key` |
|
|
183
|
+
|
|
184
|
+
Use the provided constants for autocomplete, or pass a string:
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
from screenshotscout import CaptureFormat, CaptureOptions, CaptureWaitUntil
|
|
188
|
+
|
|
189
|
+
options = CaptureOptions(
|
|
190
|
+
format=CaptureFormat.WEBP,
|
|
191
|
+
wait_until=CaptureWaitUntil.LOAD,
|
|
192
|
+
)
|
|
193
|
+
response = client.capture("https://example.com", options)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
See the [screenshot option reference](https://screenshotscout.com/docs/screenshot-options) for
|
|
197
|
+
available values and examples.
|
|
198
|
+
|
|
199
|
+
## Timeouts
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
import os
|
|
203
|
+
|
|
204
|
+
from screenshotscout import CaptureOptions, ScreenshotScoutClient
|
|
205
|
+
|
|
206
|
+
with ScreenshotScoutClient(
|
|
207
|
+
os.environ["SCREENSHOTSCOUT_ACCESS_KEY"],
|
|
208
|
+
request_timeout=300.0,
|
|
209
|
+
) as client:
|
|
210
|
+
response = client.capture(
|
|
211
|
+
"https://example.com",
|
|
212
|
+
CaptureOptions(timeout=180),
|
|
213
|
+
)
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
`CaptureOptions.timeout` controls how long Screenshot Scout may spend capturing the page.
|
|
217
|
+
`request_timeout` controls how long your application waits for the API response.
|
|
218
|
+
|
|
219
|
+
## Responses
|
|
220
|
+
|
|
221
|
+
- `BinaryCaptureResponse` provides the screenshot as `bytes`, along with URL, expiry, and cache
|
|
222
|
+
information when available.
|
|
223
|
+
- `JsonCaptureResponse` provides screenshot metadata in `result`.
|
|
224
|
+
|
|
225
|
+
Both response types include `raw_response` for access to the HTTP status, headers, content type,
|
|
226
|
+
and body.
|
|
227
|
+
|
|
228
|
+
## Error handling
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
import os
|
|
232
|
+
|
|
233
|
+
from screenshotscout import (
|
|
234
|
+
ScreenshotScoutAPIError,
|
|
235
|
+
ScreenshotScoutClient,
|
|
236
|
+
ScreenshotScoutError,
|
|
237
|
+
ScreenshotScoutTransportError,
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
try:
|
|
241
|
+
with ScreenshotScoutClient(os.environ["SCREENSHOTSCOUT_ACCESS_KEY"]) as client:
|
|
242
|
+
response = client.capture("https://example.com")
|
|
243
|
+
except ScreenshotScoutAPIError as error:
|
|
244
|
+
print(error.status, error.error_code, error.error_message)
|
|
245
|
+
except ScreenshotScoutTransportError as error:
|
|
246
|
+
print(error.cause)
|
|
247
|
+
except ScreenshotScoutError as error:
|
|
248
|
+
print(error)
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
The SDK does not automatically retry failed requests.
|
|
252
|
+
|
|
253
|
+
## Examples
|
|
254
|
+
|
|
255
|
+
Runnable programs are available in [`examples`](examples):
|
|
256
|
+
|
|
257
|
+
- [`binary_capture.py`](examples/binary_capture.py)
|
|
258
|
+
- [`json_capture.py`](examples/json_capture.py)
|
|
259
|
+
- [`async_client.py`](examples/async_client.py)
|
|
260
|
+
- [`capture_url.py`](examples/capture_url.py)
|
|
261
|
+
|
|
262
|
+
## Development
|
|
263
|
+
|
|
264
|
+
Create a virtual environment and install the package with its development tools:
|
|
265
|
+
|
|
266
|
+
```shell
|
|
267
|
+
python -m venv .venv
|
|
268
|
+
python -m pip install --upgrade pip
|
|
269
|
+
python -m pip install -e ".[dev]"
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Run the local checks:
|
|
273
|
+
|
|
274
|
+
```shell
|
|
275
|
+
python -m ruff format --check .
|
|
276
|
+
python -m ruff check .
|
|
277
|
+
python -m mypy
|
|
278
|
+
python -m pytest
|
|
279
|
+
python -m build
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## License
|
|
283
|
+
|
|
284
|
+
This project is licensed under the MIT License. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Screenshot Scout Python examples
|
|
2
|
+
|
|
3
|
+
Install the package, set `SCREENSHOTSCOUT_ACCESS_KEY`, and run an example from the repository root:
|
|
4
|
+
|
|
5
|
+
```shell
|
|
6
|
+
python -m pip install -e .
|
|
7
|
+
python examples/binary_capture.py
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
The examples read credentials explicitly and pass them to the SDK. For signed requests or signed
|
|
11
|
+
capture URLs, also set `SCREENSHOTSCOUT_SECRET_KEY`.
|
|
12
|
+
|
|
13
|
+
- `binary_capture.py` saves a WebP capture as `screenshot.webp`.
|
|
14
|
+
- `json_capture.py` requests a JSON result and prints the screenshot URL.
|
|
15
|
+
- `async_client.py` uses async Python I/O and waits for the inline binary response.
|
|
16
|
+
- `capture_url.py` builds a sensitive capture URL without making a network request.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Use async Python I/O while waiting for the inline capture response."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
from screenshotscout import AsyncScreenshotScoutClient, BinaryCaptureResponse, CaptureOptions
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async def main() -> None:
|
|
10
|
+
options = CaptureOptions(full_page=True)
|
|
11
|
+
|
|
12
|
+
async with AsyncScreenshotScoutClient(os.environ["SCREENSHOTSCOUT_ACCESS_KEY"]) as client:
|
|
13
|
+
response = await client.capture("https://example.com", options)
|
|
14
|
+
|
|
15
|
+
if not isinstance(response, BinaryCaptureResponse):
|
|
16
|
+
raise RuntimeError("Expected a binary capture response.")
|
|
17
|
+
|
|
18
|
+
print(f"Received {len(response.bytes)} bytes")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
if __name__ == "__main__":
|
|
22
|
+
asyncio.run(main())
|