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.
@@ -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())