nocode-amazon 0.0.1__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.
- nocode_amazon-0.0.1/LICENSE +21 -0
- nocode_amazon-0.0.1/MANIFEST.in +2 -0
- nocode_amazon-0.0.1/PKG-INFO +244 -0
- nocode_amazon-0.0.1/README.md +214 -0
- nocode_amazon-0.0.1/pyproject.toml +38 -0
- nocode_amazon-0.0.1/setup.cfg +4 -0
- nocode_amazon-0.0.1/src/nocode_amazon/__init__.py +6 -0
- nocode_amazon-0.0.1/src/nocode_amazon/client.py +205 -0
- nocode_amazon-0.0.1/src/nocode_amazon.egg-info/PKG-INFO +244 -0
- nocode_amazon-0.0.1/src/nocode_amazon.egg-info/SOURCES.txt +11 -0
- nocode_amazon-0.0.1/src/nocode_amazon.egg-info/dependency_links.txt +1 -0
- nocode_amazon-0.0.1/src/nocode_amazon.egg-info/requires.txt +1 -0
- nocode_amazon-0.0.1/src/nocode_amazon.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 wordstotech
|
|
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,244 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nocode-amazon
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: No code Amazon scraper and Amazon API client: search, product, pricing and featured or sponsored placements via ScrapingBee.
|
|
5
|
+
Author: wordstotech
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/ScrapingBee/nocode-amazon
|
|
8
|
+
Project-URL: Repository, https://github.com/ScrapingBee/nocode-amazon
|
|
9
|
+
Project-URL: Documentation, https://www.scrapingbee.com/documentation/
|
|
10
|
+
Keywords: amazon scraper,amazon api,no code scraper,scrape amazon products,amazon product scraper,amazon featured products,web scraping,scrapingbee
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Classifier: Topic :: Text Processing :: Markup :: HTML
|
|
25
|
+
Requires-Python: >=3.8
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: requests>=2.25.0
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# nocode-amazon
|
|
32
|
+
|
|
33
|
+
A Python client for ScrapingBee's three dedicated Amazon endpoints, plus the helpers that separate paid placements from earned ones.
|
|
34
|
+
|
|
35
|
+
The package name comes from the no code Make and Airtable workflow this grew out of. The library is the code path for people who outgrew the spreadsheet: same data, same public Amazon pages, no visual scenario to maintain.
|
|
36
|
+
|
|
37
|
+
**Verified against the live API on 2026-09-10.** Every parameter name, response field and credit figure below came back from a real call. Where the documentation and the API disagreed, the API won and the difference is noted.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install nocode-amazon
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Requires Python 3.8 or newer and `requests`.
|
|
44
|
+
|
|
45
|
+
## Authentication
|
|
46
|
+
|
|
47
|
+
Header based, on every request:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
Authorization: Bearer YOUR_API_KEY
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The `api_key` query parameter still answers but the current documentation marks it deprecated. This client sends the header.
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from nocode_amazon import AmazonScraper
|
|
57
|
+
|
|
58
|
+
bee = AmazonScraper("YOUR_API_KEY")
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Get a key and 1,000 free credits from [ScrapingBee](https://www.scrapingbee.com/). Full reference: [Amazon API documentation](https://www.scrapingbee.com/documentation/amazon/).
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Endpoint reference
|
|
66
|
+
|
|
67
|
+
### `search(query, pages=1, **params)`
|
|
68
|
+
|
|
69
|
+
`GET /api/v1/amazon/search`. **5 credits per page.**
|
|
70
|
+
|
|
71
|
+
Amazon search results as structured JSON. No HTML, no selectors.
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
page = bee.search("fitness tracker")
|
|
75
|
+
page["products_count"] # 23
|
|
76
|
+
page["products"] # list of product dicts
|
|
77
|
+
page["refinements"] # Amazon's own facets for this query
|
|
78
|
+
page["url"] # the Amazon URL that was fetched
|
|
79
|
+
page["page"] # 1
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Live call on `fitness tracker` returned 23 products and a `refinements` object with 53 facet groups, including `brands`, `band_color`, `band_material_type`, `battery_average_life`, `battery_charge_time` and `case_diameter`.
|
|
83
|
+
|
|
84
|
+
Optional parameters, all verified present on the endpoint:
|
|
85
|
+
|
|
86
|
+
| Parameter | Notes |
|
|
87
|
+
|---|---|
|
|
88
|
+
| `pages` | Pages to fetch. Billed per page |
|
|
89
|
+
| `sort_by` | `featured`, `most_recent`, `price_low_to_high`, `price_high_to_low`, `average_review`, `bestsellers` |
|
|
90
|
+
| `category_id` | Restrict to one Amazon category |
|
|
91
|
+
| `merchant_id` | Restrict to one seller |
|
|
92
|
+
| `domain` | Marketplace top level domain: `com`, `co.uk`, `de`, `in` |
|
|
93
|
+
| `country` | Proxy geolocation |
|
|
94
|
+
| `currency` | ISO 4217 display currency |
|
|
95
|
+
| `language` | ISO language code |
|
|
96
|
+
| `device` | `desktop` or `mobile` |
|
|
97
|
+
| `zip_code` | Postal code. Changes prices and delivery promises |
|
|
98
|
+
| `light_request` | Default `True` at 5 credits. `False` forces a browser at 15 |
|
|
99
|
+
| `add_html` | Include the raw page alongside the JSON |
|
|
100
|
+
| `autoselect_variant` | Pick a variant automatically |
|
|
101
|
+
| `screenshot` | Capture the page. Always 15 credits, ignores `light_request` |
|
|
102
|
+
| `tag` | Your own label, returned in the response headers |
|
|
103
|
+
|
|
104
|
+
Related landing pages: [Amazon search API](https://www.scrapingbee.com/scrapers/amazon-search-api/), [Amazon keyword scraper API](https://www.scrapingbee.com/scrapers/amazon-keyword-scraper-api/), [Amazon organic results API](https://www.scrapingbee.com/scrapers/amazon-organic-results-api/), [Amazon filters API](https://www.scrapingbee.com/scrapers/amazon-filters-api/), [Amazon related searches API](https://www.scrapingbee.com/scrapers/amazon-related-searches-api/), [Amazon spell check API](https://www.scrapingbee.com/scrapers/amazon-spell-check-api/), [Amazon zip code API](https://www.scrapingbee.com/scrapers/amazon-zip-code-api/).
|
|
105
|
+
|
|
106
|
+
### `product(asin, **params)`
|
|
107
|
+
|
|
108
|
+
`GET /api/v1/amazon/product`. **5 credits.**
|
|
109
|
+
|
|
110
|
+
**The wire parameter is `query`, not `asin`.** The value has to be a valid 10 character ASIN, but the field is named `query`. This client takes `asin` as its argument name and sends `query` for you.
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
detail = bee.product("B0GTMTZF3V")
|
|
114
|
+
detail["brand"] # 'Fitbit'
|
|
115
|
+
detail["price"] # 99.99
|
|
116
|
+
detail["currency"] # 'USD'
|
|
117
|
+
detail["rating"] # 4.3
|
|
118
|
+
detail["reviews_count"] # 2036
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The live response carried **56 top level keys**. The ones worth knowing:
|
|
122
|
+
|
|
123
|
+
| Field | Contents |
|
|
124
|
+
|---|---|
|
|
125
|
+
| `bullet_points` | The feature bullets, newline separated |
|
|
126
|
+
| `category` | A `ladder` of breadcrumb steps, each with `name` and `url` |
|
|
127
|
+
| `featured_merchant` | `name`, `seller_id`, `shipped_from`, `is_amazon_fulfilled` |
|
|
128
|
+
| `product_details` | Spec table as key and value pairs, including `best_sellers_rank` |
|
|
129
|
+
| `technical_details` | The second spec table |
|
|
130
|
+
| `rating_stars_distribution` | Review counts per star rating |
|
|
131
|
+
| `sales_rank` | Category rank entries |
|
|
132
|
+
| `variations` | Other sizes, colours and configurations |
|
|
133
|
+
| `images` | Image URLs |
|
|
134
|
+
| `delivery` | Delivery promises with type and date |
|
|
135
|
+
| `pricing_url` | The offer listing page for this ASIN |
|
|
136
|
+
| `parent_asin` | The variation parent |
|
|
137
|
+
| `discount_percentage`, `price_strikethrough`, `coupon` | Promotion state |
|
|
138
|
+
| `stock`, `max_quantity` | Availability |
|
|
139
|
+
|
|
140
|
+
Related: [Amazon ASIN API](https://www.scrapingbee.com/scrapers/amazon-asin-api/), [Amazon image API](https://www.scrapingbee.com/scrapers/amazon-image-api/), [Amazon review API](https://www.scrapingbee.com/scrapers/amazon-review-api/), [Amazon best sellers API](https://www.scrapingbee.com/scrapers/amazon-best-sellers-api/), [Amazon video results API](https://www.scrapingbee.com/scrapers/amazon-video-results-api/), [Amazon URL API](https://www.scrapingbee.com/scrapers/amazon-ulr-api/).
|
|
141
|
+
|
|
142
|
+
### `pricing(asin, **params)`
|
|
143
|
+
|
|
144
|
+
`GET /api/v1/amazon/pricing`. **5 credits.**
|
|
145
|
+
|
|
146
|
+
**This endpoint takes `asin` on the wire.** Search and product both take `query`. Pricing does not, and it rejects `query` explicitly:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{"errors": {"query": {"asin": ["Missing data for required field."], "query": ["Unknown field."]}}}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
That rejected call was billed **0 credits**, confirmed by `spb-cost: 0` on the response. This client raises `ScrapingBeeError` with the API's own error dict in `.payload`, so the offending field is never a guess.
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
offers = bee.pricing("B0GTMTZF3V")
|
|
156
|
+
for offer in offers["pricing"]:
|
|
157
|
+
print(offer["seller"], offer["price"], offer["condition"])
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Each offer carries `seller`, `seller_id`, `seller_link`, `condition`, `price`, `price_shipping`, `currency`, `rating_count` and a `delivery_options` list.
|
|
161
|
+
|
|
162
|
+
Related: [Amazon offers API](https://www.scrapingbee.com/scrapers/amazon-offers-api/), [Amazon seller API](https://www.scrapingbee.com/scrapers/amazon-seller-api/), [Amazon vendor API](https://www.scrapingbee.com/scrapers/amazon-vendor-api/), [Amazon shipping API](https://www.scrapingbee.com/scrapers/amazon-shipping-api/).
|
|
163
|
+
|
|
164
|
+
### `usage()`
|
|
165
|
+
|
|
166
|
+
`GET /api/v1/usage`. **Free.**
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
bee.usage()
|
|
170
|
+
# {'max_api_credit': 1000000, 'used_api_credit': 353946,
|
|
171
|
+
# 'max_concurrency': 100, 'current_concurrency': 0,
|
|
172
|
+
# 'renewal_subscription_date': '2026-09-21T12:06:28'}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Call this before a large run. Note it lags by minutes, so do not read it immediately afterwards to compute what a batch cost.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Placement helpers
|
|
180
|
+
|
|
181
|
+
Amazon search markup gives every card the same classes, so CSS selectors cannot tell a paid slot from an earned rank. The endpoint labels each result instead, which turns the problem into a filter.
|
|
182
|
+
|
|
183
|
+
Per product placement fields:
|
|
184
|
+
|
|
185
|
+
| Field | Type | Meaning |
|
|
186
|
+
|---|---|---|
|
|
187
|
+
| `is_sponsored` | bool | Paid placement |
|
|
188
|
+
| `sponsored_position` | int or None | Rank among the ads |
|
|
189
|
+
| `organic_position` | int or None | Rank among earned results |
|
|
190
|
+
| `is_amazons_choice` | bool | Amazon's Choice badge |
|
|
191
|
+
| `best_seller` | bool | Best Seller badge |
|
|
192
|
+
| `sales_volume` | str | For example `10K+ bought in past month` |
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
page = bee.search("fitness tracker", sort_by="featured")
|
|
196
|
+
|
|
197
|
+
AmazonScraper.featured(page) # sponsored, ordered by ad slot
|
|
198
|
+
AmazonScraper.organic(page) # earned, ordered by organic rank
|
|
199
|
+
AmazonScraper.badged(page) # Amazon's Choice or Best Seller
|
|
200
|
+
AmazonScraper.facets(page) # the refinements object
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Two live runs on the same query returned 7 featured of 24 products, then 9 of 26. Paid density moves between requests, so measure it rather than assuming a fixed ratio.
|
|
204
|
+
|
|
205
|
+
`is_prime` came back `False` on every row of both pages, so verify it against your own target category before building a Prime filter on it.
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Credit cost
|
|
210
|
+
|
|
211
|
+
Measured from `spb-cost` response headers, not quoted from a pricing page. This client stores the value on `bee.last_cost` after every call.
|
|
212
|
+
|
|
213
|
+
| Call | Credits |
|
|
214
|
+
|---|---|
|
|
215
|
+
| Search, default light request | 5 per page |
|
|
216
|
+
| Search, `light_request=False` | 15 per page |
|
|
217
|
+
| Product, default | 5 |
|
|
218
|
+
| Product, `light_request=False` | 15 |
|
|
219
|
+
| Pricing | 5 |
|
|
220
|
+
| Any screenshot | 15 |
|
|
221
|
+
| Rejected request | 0 |
|
|
222
|
+
| `usage()` | 0 |
|
|
223
|
+
|
|
224
|
+
Light requests skip the browser. They were sufficient for search, product and pricing on every call made here. Turn them off when you need review text or other content that appears only after JavaScript runs.
|
|
225
|
+
|
|
226
|
+
Failed requests are retried inside the API for up to 30 seconds, so set client timeouts above that. This client defaults to 60 seconds.
|
|
227
|
+
|
|
228
|
+
Plan tiers: [ScrapingBee pricing](https://www.scrapingbee.com/pricing).
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Scope
|
|
233
|
+
|
|
234
|
+
Public Amazon listing and product pages. Nothing in this package signs in, and scraping under login credentials is prohibited by ScrapingBee's terms of service.
|
|
235
|
+
|
|
236
|
+
## Related features
|
|
237
|
+
|
|
238
|
+
[AI web scraping](https://www.scrapingbee.com/features/ai-web-scraping-api/), [data extraction rules](https://www.scrapingbee.com/features/data-extraction/), [Amazon feature page](https://www.scrapingbee.com/features/amazon/), [screenshots](https://www.scrapingbee.com/features/screenshot/), [markdown scraper](https://www.scrapingbee.com/features/markdown-scraper/), [Make integration](https://www.scrapingbee.com/features/make/), [n8n integration](https://www.scrapingbee.com/features/n8n/), [Zapier integration](https://www.scrapingbee.com/features/zapier/).
|
|
239
|
+
|
|
240
|
+
The no code version of this workflow, with the Make scenario and the extraction rules, is at [github.com/ScrapingBee/nocode-amazon](https://github.com/ScrapingBee/nocode-amazon).
|
|
241
|
+
|
|
242
|
+
## License
|
|
243
|
+
|
|
244
|
+
MIT
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# nocode-amazon
|
|
2
|
+
|
|
3
|
+
A Python client for ScrapingBee's three dedicated Amazon endpoints, plus the helpers that separate paid placements from earned ones.
|
|
4
|
+
|
|
5
|
+
The package name comes from the no code Make and Airtable workflow this grew out of. The library is the code path for people who outgrew the spreadsheet: same data, same public Amazon pages, no visual scenario to maintain.
|
|
6
|
+
|
|
7
|
+
**Verified against the live API on 2026-09-10.** Every parameter name, response field and credit figure below came back from a real call. Where the documentation and the API disagreed, the API won and the difference is noted.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install nocode-amazon
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Requires Python 3.8 or newer and `requests`.
|
|
14
|
+
|
|
15
|
+
## Authentication
|
|
16
|
+
|
|
17
|
+
Header based, on every request:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
Authorization: Bearer YOUR_API_KEY
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The `api_key` query parameter still answers but the current documentation marks it deprecated. This client sends the header.
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from nocode_amazon import AmazonScraper
|
|
27
|
+
|
|
28
|
+
bee = AmazonScraper("YOUR_API_KEY")
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Get a key and 1,000 free credits from [ScrapingBee](https://www.scrapingbee.com/). Full reference: [Amazon API documentation](https://www.scrapingbee.com/documentation/amazon/).
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Endpoint reference
|
|
36
|
+
|
|
37
|
+
### `search(query, pages=1, **params)`
|
|
38
|
+
|
|
39
|
+
`GET /api/v1/amazon/search`. **5 credits per page.**
|
|
40
|
+
|
|
41
|
+
Amazon search results as structured JSON. No HTML, no selectors.
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
page = bee.search("fitness tracker")
|
|
45
|
+
page["products_count"] # 23
|
|
46
|
+
page["products"] # list of product dicts
|
|
47
|
+
page["refinements"] # Amazon's own facets for this query
|
|
48
|
+
page["url"] # the Amazon URL that was fetched
|
|
49
|
+
page["page"] # 1
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Live call on `fitness tracker` returned 23 products and a `refinements` object with 53 facet groups, including `brands`, `band_color`, `band_material_type`, `battery_average_life`, `battery_charge_time` and `case_diameter`.
|
|
53
|
+
|
|
54
|
+
Optional parameters, all verified present on the endpoint:
|
|
55
|
+
|
|
56
|
+
| Parameter | Notes |
|
|
57
|
+
|---|---|
|
|
58
|
+
| `pages` | Pages to fetch. Billed per page |
|
|
59
|
+
| `sort_by` | `featured`, `most_recent`, `price_low_to_high`, `price_high_to_low`, `average_review`, `bestsellers` |
|
|
60
|
+
| `category_id` | Restrict to one Amazon category |
|
|
61
|
+
| `merchant_id` | Restrict to one seller |
|
|
62
|
+
| `domain` | Marketplace top level domain: `com`, `co.uk`, `de`, `in` |
|
|
63
|
+
| `country` | Proxy geolocation |
|
|
64
|
+
| `currency` | ISO 4217 display currency |
|
|
65
|
+
| `language` | ISO language code |
|
|
66
|
+
| `device` | `desktop` or `mobile` |
|
|
67
|
+
| `zip_code` | Postal code. Changes prices and delivery promises |
|
|
68
|
+
| `light_request` | Default `True` at 5 credits. `False` forces a browser at 15 |
|
|
69
|
+
| `add_html` | Include the raw page alongside the JSON |
|
|
70
|
+
| `autoselect_variant` | Pick a variant automatically |
|
|
71
|
+
| `screenshot` | Capture the page. Always 15 credits, ignores `light_request` |
|
|
72
|
+
| `tag` | Your own label, returned in the response headers |
|
|
73
|
+
|
|
74
|
+
Related landing pages: [Amazon search API](https://www.scrapingbee.com/scrapers/amazon-search-api/), [Amazon keyword scraper API](https://www.scrapingbee.com/scrapers/amazon-keyword-scraper-api/), [Amazon organic results API](https://www.scrapingbee.com/scrapers/amazon-organic-results-api/), [Amazon filters API](https://www.scrapingbee.com/scrapers/amazon-filters-api/), [Amazon related searches API](https://www.scrapingbee.com/scrapers/amazon-related-searches-api/), [Amazon spell check API](https://www.scrapingbee.com/scrapers/amazon-spell-check-api/), [Amazon zip code API](https://www.scrapingbee.com/scrapers/amazon-zip-code-api/).
|
|
75
|
+
|
|
76
|
+
### `product(asin, **params)`
|
|
77
|
+
|
|
78
|
+
`GET /api/v1/amazon/product`. **5 credits.**
|
|
79
|
+
|
|
80
|
+
**The wire parameter is `query`, not `asin`.** The value has to be a valid 10 character ASIN, but the field is named `query`. This client takes `asin` as its argument name and sends `query` for you.
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
detail = bee.product("B0GTMTZF3V")
|
|
84
|
+
detail["brand"] # 'Fitbit'
|
|
85
|
+
detail["price"] # 99.99
|
|
86
|
+
detail["currency"] # 'USD'
|
|
87
|
+
detail["rating"] # 4.3
|
|
88
|
+
detail["reviews_count"] # 2036
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The live response carried **56 top level keys**. The ones worth knowing:
|
|
92
|
+
|
|
93
|
+
| Field | Contents |
|
|
94
|
+
|---|---|
|
|
95
|
+
| `bullet_points` | The feature bullets, newline separated |
|
|
96
|
+
| `category` | A `ladder` of breadcrumb steps, each with `name` and `url` |
|
|
97
|
+
| `featured_merchant` | `name`, `seller_id`, `shipped_from`, `is_amazon_fulfilled` |
|
|
98
|
+
| `product_details` | Spec table as key and value pairs, including `best_sellers_rank` |
|
|
99
|
+
| `technical_details` | The second spec table |
|
|
100
|
+
| `rating_stars_distribution` | Review counts per star rating |
|
|
101
|
+
| `sales_rank` | Category rank entries |
|
|
102
|
+
| `variations` | Other sizes, colours and configurations |
|
|
103
|
+
| `images` | Image URLs |
|
|
104
|
+
| `delivery` | Delivery promises with type and date |
|
|
105
|
+
| `pricing_url` | The offer listing page for this ASIN |
|
|
106
|
+
| `parent_asin` | The variation parent |
|
|
107
|
+
| `discount_percentage`, `price_strikethrough`, `coupon` | Promotion state |
|
|
108
|
+
| `stock`, `max_quantity` | Availability |
|
|
109
|
+
|
|
110
|
+
Related: [Amazon ASIN API](https://www.scrapingbee.com/scrapers/amazon-asin-api/), [Amazon image API](https://www.scrapingbee.com/scrapers/amazon-image-api/), [Amazon review API](https://www.scrapingbee.com/scrapers/amazon-review-api/), [Amazon best sellers API](https://www.scrapingbee.com/scrapers/amazon-best-sellers-api/), [Amazon video results API](https://www.scrapingbee.com/scrapers/amazon-video-results-api/), [Amazon URL API](https://www.scrapingbee.com/scrapers/amazon-ulr-api/).
|
|
111
|
+
|
|
112
|
+
### `pricing(asin, **params)`
|
|
113
|
+
|
|
114
|
+
`GET /api/v1/amazon/pricing`. **5 credits.**
|
|
115
|
+
|
|
116
|
+
**This endpoint takes `asin` on the wire.** Search and product both take `query`. Pricing does not, and it rejects `query` explicitly:
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{"errors": {"query": {"asin": ["Missing data for required field."], "query": ["Unknown field."]}}}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
That rejected call was billed **0 credits**, confirmed by `spb-cost: 0` on the response. This client raises `ScrapingBeeError` with the API's own error dict in `.payload`, so the offending field is never a guess.
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
offers = bee.pricing("B0GTMTZF3V")
|
|
126
|
+
for offer in offers["pricing"]:
|
|
127
|
+
print(offer["seller"], offer["price"], offer["condition"])
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Each offer carries `seller`, `seller_id`, `seller_link`, `condition`, `price`, `price_shipping`, `currency`, `rating_count` and a `delivery_options` list.
|
|
131
|
+
|
|
132
|
+
Related: [Amazon offers API](https://www.scrapingbee.com/scrapers/amazon-offers-api/), [Amazon seller API](https://www.scrapingbee.com/scrapers/amazon-seller-api/), [Amazon vendor API](https://www.scrapingbee.com/scrapers/amazon-vendor-api/), [Amazon shipping API](https://www.scrapingbee.com/scrapers/amazon-shipping-api/).
|
|
133
|
+
|
|
134
|
+
### `usage()`
|
|
135
|
+
|
|
136
|
+
`GET /api/v1/usage`. **Free.**
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
bee.usage()
|
|
140
|
+
# {'max_api_credit': 1000000, 'used_api_credit': 353946,
|
|
141
|
+
# 'max_concurrency': 100, 'current_concurrency': 0,
|
|
142
|
+
# 'renewal_subscription_date': '2026-09-21T12:06:28'}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Call this before a large run. Note it lags by minutes, so do not read it immediately afterwards to compute what a batch cost.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Placement helpers
|
|
150
|
+
|
|
151
|
+
Amazon search markup gives every card the same classes, so CSS selectors cannot tell a paid slot from an earned rank. The endpoint labels each result instead, which turns the problem into a filter.
|
|
152
|
+
|
|
153
|
+
Per product placement fields:
|
|
154
|
+
|
|
155
|
+
| Field | Type | Meaning |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| `is_sponsored` | bool | Paid placement |
|
|
158
|
+
| `sponsored_position` | int or None | Rank among the ads |
|
|
159
|
+
| `organic_position` | int or None | Rank among earned results |
|
|
160
|
+
| `is_amazons_choice` | bool | Amazon's Choice badge |
|
|
161
|
+
| `best_seller` | bool | Best Seller badge |
|
|
162
|
+
| `sales_volume` | str | For example `10K+ bought in past month` |
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
page = bee.search("fitness tracker", sort_by="featured")
|
|
166
|
+
|
|
167
|
+
AmazonScraper.featured(page) # sponsored, ordered by ad slot
|
|
168
|
+
AmazonScraper.organic(page) # earned, ordered by organic rank
|
|
169
|
+
AmazonScraper.badged(page) # Amazon's Choice or Best Seller
|
|
170
|
+
AmazonScraper.facets(page) # the refinements object
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Two live runs on the same query returned 7 featured of 24 products, then 9 of 26. Paid density moves between requests, so measure it rather than assuming a fixed ratio.
|
|
174
|
+
|
|
175
|
+
`is_prime` came back `False` on every row of both pages, so verify it against your own target category before building a Prime filter on it.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Credit cost
|
|
180
|
+
|
|
181
|
+
Measured from `spb-cost` response headers, not quoted from a pricing page. This client stores the value on `bee.last_cost` after every call.
|
|
182
|
+
|
|
183
|
+
| Call | Credits |
|
|
184
|
+
|---|---|
|
|
185
|
+
| Search, default light request | 5 per page |
|
|
186
|
+
| Search, `light_request=False` | 15 per page |
|
|
187
|
+
| Product, default | 5 |
|
|
188
|
+
| Product, `light_request=False` | 15 |
|
|
189
|
+
| Pricing | 5 |
|
|
190
|
+
| Any screenshot | 15 |
|
|
191
|
+
| Rejected request | 0 |
|
|
192
|
+
| `usage()` | 0 |
|
|
193
|
+
|
|
194
|
+
Light requests skip the browser. They were sufficient for search, product and pricing on every call made here. Turn them off when you need review text or other content that appears only after JavaScript runs.
|
|
195
|
+
|
|
196
|
+
Failed requests are retried inside the API for up to 30 seconds, so set client timeouts above that. This client defaults to 60 seconds.
|
|
197
|
+
|
|
198
|
+
Plan tiers: [ScrapingBee pricing](https://www.scrapingbee.com/pricing).
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Scope
|
|
203
|
+
|
|
204
|
+
Public Amazon listing and product pages. Nothing in this package signs in, and scraping under login credentials is prohibited by ScrapingBee's terms of service.
|
|
205
|
+
|
|
206
|
+
## Related features
|
|
207
|
+
|
|
208
|
+
[AI web scraping](https://www.scrapingbee.com/features/ai-web-scraping-api/), [data extraction rules](https://www.scrapingbee.com/features/data-extraction/), [Amazon feature page](https://www.scrapingbee.com/features/amazon/), [screenshots](https://www.scrapingbee.com/features/screenshot/), [markdown scraper](https://www.scrapingbee.com/features/markdown-scraper/), [Make integration](https://www.scrapingbee.com/features/make/), [n8n integration](https://www.scrapingbee.com/features/n8n/), [Zapier integration](https://www.scrapingbee.com/features/zapier/).
|
|
209
|
+
|
|
210
|
+
The no code version of this workflow, with the Make scenario and the extraction rules, is at [github.com/ScrapingBee/nocode-amazon](https://github.com/ScrapingBee/nocode-amazon).
|
|
211
|
+
|
|
212
|
+
## License
|
|
213
|
+
|
|
214
|
+
MIT
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "nocode-amazon"
|
|
7
|
+
version = "0.0.1"
|
|
8
|
+
description = "No code Amazon scraper and Amazon API client: search, product, pricing and featured or sponsored placements via ScrapingBee."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "wordstotech" }]
|
|
13
|
+
keywords = ["amazon scraper", "amazon api", "no code scraper", "scrape amazon products", "amazon product scraper", "amazon featured products", "web scraping", "scrapingbee"]
|
|
14
|
+
dependencies = ["requests>=2.25.0"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.8",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
"Topic :: Internet :: WWW/HTTP",
|
|
28
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
29
|
+
"Topic :: Text Processing :: Markup :: HTML",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://github.com/ScrapingBee/nocode-amazon"
|
|
34
|
+
Repository = "https://github.com/ScrapingBee/nocode-amazon"
|
|
35
|
+
Documentation = "https://www.scrapingbee.com/documentation/"
|
|
36
|
+
|
|
37
|
+
[tool.setuptools.packages.find]
|
|
38
|
+
where = ["src"]
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"""ScrapingBee Amazon API client.
|
|
2
|
+
|
|
3
|
+
Every endpoint, parameter name and credit figure here was verified against
|
|
4
|
+
the live API on 2026-09-10. Auth is the Authorization Bearer header, which
|
|
5
|
+
is what the current documentation uses. The api_key query parameter still
|
|
6
|
+
answers but is marked deprecated.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import Any, Dict, List, Optional
|
|
12
|
+
|
|
13
|
+
import requests
|
|
14
|
+
|
|
15
|
+
__all__ = ["AmazonScraper", "ScrapingBeeError"]
|
|
16
|
+
|
|
17
|
+
BASE_URL = "https://app.scrapingbee.com/api/v1"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ScrapingBeeError(RuntimeError):
|
|
21
|
+
"""Raised when the API returns a validation error or a failed request."""
|
|
22
|
+
|
|
23
|
+
def __init__(self, message: str, status: Optional[int] = None,
|
|
24
|
+
payload: Any = None) -> None:
|
|
25
|
+
super().__init__(message)
|
|
26
|
+
self.status = status
|
|
27
|
+
self.payload = payload
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class AmazonScraper:
|
|
31
|
+
"""Client for the three dedicated ScrapingBee Amazon endpoints.
|
|
32
|
+
|
|
33
|
+
>>> bee = AmazonScraper("YOUR_API_KEY")
|
|
34
|
+
>>> page = bee.search("fitness tracker")
|
|
35
|
+
>>> len(bee.featured(page))
|
|
36
|
+
3
|
|
37
|
+
|
|
38
|
+
Credit cost, measured live: 5 per call on a light request, 15 with
|
|
39
|
+
``light_request=False``, 15 for any screenshot, 0 for a rejected
|
|
40
|
+
request. Search bills per page.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(self, api_key: str, base_url: str = BASE_URL,
|
|
44
|
+
timeout: int = 60, session: Optional[requests.Session] = None) -> None:
|
|
45
|
+
if not api_key:
|
|
46
|
+
raise ValueError("api_key is required")
|
|
47
|
+
self.api_key = api_key
|
|
48
|
+
self.base_url = base_url.rstrip("/")
|
|
49
|
+
self.timeout = timeout
|
|
50
|
+
self._session = session or requests.Session()
|
|
51
|
+
self.last_cost: Optional[int] = None
|
|
52
|
+
|
|
53
|
+
# ------------------------------------------------------------------ core
|
|
54
|
+
|
|
55
|
+
def _get(self, path: str, params: Dict[str, Any]) -> Dict[str, Any]:
|
|
56
|
+
clean = {k: v for k, v in params.items() if v is not None}
|
|
57
|
+
for key, value in list(clean.items()):
|
|
58
|
+
if isinstance(value, bool):
|
|
59
|
+
clean[key] = "true" if value else "false"
|
|
60
|
+
|
|
61
|
+
response = self._session.get(
|
|
62
|
+
f"{self.base_url}/{path}",
|
|
63
|
+
headers={"Authorization": f"Bearer {self.api_key}"},
|
|
64
|
+
params=clean,
|
|
65
|
+
timeout=self.timeout,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# Cost arrives as a response header. Names are lowercased over HTTP/2.
|
|
69
|
+
cost = response.headers.get("spb-cost")
|
|
70
|
+
self.last_cost = int(cost) if cost and cost.isdigit() else None
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
body = response.json()
|
|
74
|
+
except ValueError:
|
|
75
|
+
raise ScrapingBeeError(
|
|
76
|
+
f"non JSON response ({response.status_code})",
|
|
77
|
+
response.status_code,
|
|
78
|
+
response.text[:500],
|
|
79
|
+
) from None
|
|
80
|
+
|
|
81
|
+
# The API names the offending field, so surface it rather than a guess.
|
|
82
|
+
if isinstance(body, dict) and "errors" in body:
|
|
83
|
+
raise ScrapingBeeError(
|
|
84
|
+
f"API rejected the request: {body['errors']}",
|
|
85
|
+
response.status_code,
|
|
86
|
+
body["errors"],
|
|
87
|
+
)
|
|
88
|
+
response.raise_for_status()
|
|
89
|
+
return body
|
|
90
|
+
|
|
91
|
+
# ------------------------------------------------------------- endpoints
|
|
92
|
+
|
|
93
|
+
def search(self, query: str, pages: int = 1, *, sort_by: Optional[str] = None,
|
|
94
|
+
category_id: Optional[str] = None, merchant_id: Optional[str] = None,
|
|
95
|
+
country: Optional[str] = None, currency: Optional[str] = None,
|
|
96
|
+
domain: Optional[str] = None, language: Optional[str] = None,
|
|
97
|
+
device: Optional[str] = None, zip_code: Optional[str] = None,
|
|
98
|
+
light_request: Optional[bool] = None, add_html: Optional[bool] = None,
|
|
99
|
+
autoselect_variant: Optional[bool] = None,
|
|
100
|
+
screenshot: Optional[bool] = None,
|
|
101
|
+
tag: Optional[str] = None) -> Dict[str, Any]:
|
|
102
|
+
"""Amazon search results. 5 credits per page.
|
|
103
|
+
|
|
104
|
+
Returns ``products``, ``products_count``, ``refinements``, ``url``
|
|
105
|
+
and ``page``. ``sort_by`` accepts ``featured``, ``most_recent``,
|
|
106
|
+
``price_low_to_high``, ``price_high_to_low``, ``average_review``
|
|
107
|
+
and ``bestsellers``.
|
|
108
|
+
|
|
109
|
+
``domain`` selects the marketplace, for example ``co.uk`` or ``in``.
|
|
110
|
+
``zip_code`` matters because Amazon prices and delivery promises are
|
|
111
|
+
postal code dependent.
|
|
112
|
+
"""
|
|
113
|
+
return self._get("amazon/search", {
|
|
114
|
+
"query": query, "pages": pages, "sort_by": sort_by,
|
|
115
|
+
"category_id": category_id, "merchant_id": merchant_id,
|
|
116
|
+
"country": country, "currency": currency, "domain": domain,
|
|
117
|
+
"language": language, "device": device, "zip_code": zip_code,
|
|
118
|
+
"light_request": light_request, "add_html": add_html,
|
|
119
|
+
"autoselect_variant": autoselect_variant,
|
|
120
|
+
"screenshot": screenshot, "tag": tag,
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
def product(self, asin: str, *, country: Optional[str] = None,
|
|
124
|
+
currency: Optional[str] = None, domain: Optional[str] = None,
|
|
125
|
+
language: Optional[str] = None, device: Optional[str] = None,
|
|
126
|
+
zip_code: Optional[str] = None, light_request: Optional[bool] = None,
|
|
127
|
+
add_html: Optional[bool] = None, screenshot: Optional[bool] = None,
|
|
128
|
+
tag: Optional[str] = None) -> Dict[str, Any]:
|
|
129
|
+
"""Structured product detail. 5 credits.
|
|
130
|
+
|
|
131
|
+
Note the wire parameter is ``query``, not ``asin``, even though the
|
|
132
|
+
value must be a 10 character ASIN. Sending ``asin`` here is rejected.
|
|
133
|
+
|
|
134
|
+
The live response carries 56 top level keys, including ``price``,
|
|
135
|
+
``brand``, ``rating``, ``reviews_count``, ``bullet_points``,
|
|
136
|
+
``category`` as a breadcrumb ladder, ``featured_merchant``,
|
|
137
|
+
``rating_stars_distribution``, ``sales_rank``, ``variations`` and
|
|
138
|
+
``technical_details``.
|
|
139
|
+
"""
|
|
140
|
+
return self._get("amazon/product", {
|
|
141
|
+
"query": asin, "country": country, "currency": currency,
|
|
142
|
+
"domain": domain, "language": language, "device": device,
|
|
143
|
+
"zip_code": zip_code, "light_request": light_request,
|
|
144
|
+
"add_html": add_html, "screenshot": screenshot, "tag": tag,
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
def pricing(self, asin: str, *, country: Optional[str] = None,
|
|
148
|
+
currency: Optional[str] = None, domain: Optional[str] = None,
|
|
149
|
+
language: Optional[str] = None, device: Optional[str] = None,
|
|
150
|
+
zip_code: Optional[str] = None, light_request: Optional[bool] = None,
|
|
151
|
+
add_html: Optional[bool] = None,
|
|
152
|
+
tag: Optional[str] = None) -> Dict[str, Any]:
|
|
153
|
+
"""Seller offers for one ASIN. 5 credits.
|
|
154
|
+
|
|
155
|
+
This endpoint takes ``asin`` on the wire, unlike search and product,
|
|
156
|
+
which both take ``query``. Sending ``query`` returns
|
|
157
|
+
``{"errors": {"query": {"asin": ["Missing data for required field."],
|
|
158
|
+
"query": ["Unknown field."]}}}`` and bills 0 credits.
|
|
159
|
+
|
|
160
|
+
Each entry in ``pricing`` has ``seller``, ``seller_id``,
|
|
161
|
+
``condition``, ``price``, ``price_shipping``, ``currency``,
|
|
162
|
+
``rating_count`` and ``delivery_options``.
|
|
163
|
+
"""
|
|
164
|
+
return self._get("amazon/pricing", {
|
|
165
|
+
"asin": asin, "country": country, "currency": currency,
|
|
166
|
+
"domain": domain, "language": language, "device": device,
|
|
167
|
+
"zip_code": zip_code, "light_request": light_request,
|
|
168
|
+
"add_html": add_html, "tag": tag,
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
def usage(self) -> Dict[str, Any]:
|
|
172
|
+
"""Account credit usage. Free, no credits charged."""
|
|
173
|
+
return self._get("usage", {})
|
|
174
|
+
|
|
175
|
+
# -------------------------------------------------------------- helpers
|
|
176
|
+
|
|
177
|
+
@staticmethod
|
|
178
|
+
def featured(page: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|
179
|
+
"""Paid placements from a search response, ordered by ad slot.
|
|
180
|
+
|
|
181
|
+
The endpoint labels every result, so this is a filter rather than a
|
|
182
|
+
parsing problem. CSS selectors cannot make this distinction because
|
|
183
|
+
every card shares the same markup.
|
|
184
|
+
"""
|
|
185
|
+
ads = [p for p in page.get("products", []) if p.get("is_sponsored")]
|
|
186
|
+
return sorted(ads, key=lambda p: p.get("sponsored_position") or 0)
|
|
187
|
+
|
|
188
|
+
@staticmethod
|
|
189
|
+
def organic(page: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|
190
|
+
"""Earned results from a search response, ordered by organic rank."""
|
|
191
|
+
rows = [p for p in page.get("products", []) if not p.get("is_sponsored")]
|
|
192
|
+
return sorted(rows, key=lambda p: p.get("organic_position") or 0)
|
|
193
|
+
|
|
194
|
+
@staticmethod
|
|
195
|
+
def badged(page: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|
196
|
+
"""Results carrying an Amazon's Choice or Best Seller badge."""
|
|
197
|
+
return [
|
|
198
|
+
p for p in page.get("products", [])
|
|
199
|
+
if p.get("is_amazons_choice") or p.get("best_seller")
|
|
200
|
+
]
|
|
201
|
+
|
|
202
|
+
@staticmethod
|
|
203
|
+
def facets(page: Dict[str, Any]) -> Dict[str, Any]:
|
|
204
|
+
"""Amazon's own filter facets for the query, from ``refinements``."""
|
|
205
|
+
return page.get("refinements") or {}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nocode-amazon
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: No code Amazon scraper and Amazon API client: search, product, pricing and featured or sponsored placements via ScrapingBee.
|
|
5
|
+
Author: wordstotech
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/ScrapingBee/nocode-amazon
|
|
8
|
+
Project-URL: Repository, https://github.com/ScrapingBee/nocode-amazon
|
|
9
|
+
Project-URL: Documentation, https://www.scrapingbee.com/documentation/
|
|
10
|
+
Keywords: amazon scraper,amazon api,no code scraper,scrape amazon products,amazon product scraper,amazon featured products,web scraping,scrapingbee
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Classifier: Topic :: Text Processing :: Markup :: HTML
|
|
25
|
+
Requires-Python: >=3.8
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: requests>=2.25.0
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# nocode-amazon
|
|
32
|
+
|
|
33
|
+
A Python client for ScrapingBee's three dedicated Amazon endpoints, plus the helpers that separate paid placements from earned ones.
|
|
34
|
+
|
|
35
|
+
The package name comes from the no code Make and Airtable workflow this grew out of. The library is the code path for people who outgrew the spreadsheet: same data, same public Amazon pages, no visual scenario to maintain.
|
|
36
|
+
|
|
37
|
+
**Verified against the live API on 2026-09-10.** Every parameter name, response field and credit figure below came back from a real call. Where the documentation and the API disagreed, the API won and the difference is noted.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install nocode-amazon
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Requires Python 3.8 or newer and `requests`.
|
|
44
|
+
|
|
45
|
+
## Authentication
|
|
46
|
+
|
|
47
|
+
Header based, on every request:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
Authorization: Bearer YOUR_API_KEY
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The `api_key` query parameter still answers but the current documentation marks it deprecated. This client sends the header.
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from nocode_amazon import AmazonScraper
|
|
57
|
+
|
|
58
|
+
bee = AmazonScraper("YOUR_API_KEY")
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Get a key and 1,000 free credits from [ScrapingBee](https://www.scrapingbee.com/). Full reference: [Amazon API documentation](https://www.scrapingbee.com/documentation/amazon/).
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Endpoint reference
|
|
66
|
+
|
|
67
|
+
### `search(query, pages=1, **params)`
|
|
68
|
+
|
|
69
|
+
`GET /api/v1/amazon/search`. **5 credits per page.**
|
|
70
|
+
|
|
71
|
+
Amazon search results as structured JSON. No HTML, no selectors.
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
page = bee.search("fitness tracker")
|
|
75
|
+
page["products_count"] # 23
|
|
76
|
+
page["products"] # list of product dicts
|
|
77
|
+
page["refinements"] # Amazon's own facets for this query
|
|
78
|
+
page["url"] # the Amazon URL that was fetched
|
|
79
|
+
page["page"] # 1
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Live call on `fitness tracker` returned 23 products and a `refinements` object with 53 facet groups, including `brands`, `band_color`, `band_material_type`, `battery_average_life`, `battery_charge_time` and `case_diameter`.
|
|
83
|
+
|
|
84
|
+
Optional parameters, all verified present on the endpoint:
|
|
85
|
+
|
|
86
|
+
| Parameter | Notes |
|
|
87
|
+
|---|---|
|
|
88
|
+
| `pages` | Pages to fetch. Billed per page |
|
|
89
|
+
| `sort_by` | `featured`, `most_recent`, `price_low_to_high`, `price_high_to_low`, `average_review`, `bestsellers` |
|
|
90
|
+
| `category_id` | Restrict to one Amazon category |
|
|
91
|
+
| `merchant_id` | Restrict to one seller |
|
|
92
|
+
| `domain` | Marketplace top level domain: `com`, `co.uk`, `de`, `in` |
|
|
93
|
+
| `country` | Proxy geolocation |
|
|
94
|
+
| `currency` | ISO 4217 display currency |
|
|
95
|
+
| `language` | ISO language code |
|
|
96
|
+
| `device` | `desktop` or `mobile` |
|
|
97
|
+
| `zip_code` | Postal code. Changes prices and delivery promises |
|
|
98
|
+
| `light_request` | Default `True` at 5 credits. `False` forces a browser at 15 |
|
|
99
|
+
| `add_html` | Include the raw page alongside the JSON |
|
|
100
|
+
| `autoselect_variant` | Pick a variant automatically |
|
|
101
|
+
| `screenshot` | Capture the page. Always 15 credits, ignores `light_request` |
|
|
102
|
+
| `tag` | Your own label, returned in the response headers |
|
|
103
|
+
|
|
104
|
+
Related landing pages: [Amazon search API](https://www.scrapingbee.com/scrapers/amazon-search-api/), [Amazon keyword scraper API](https://www.scrapingbee.com/scrapers/amazon-keyword-scraper-api/), [Amazon organic results API](https://www.scrapingbee.com/scrapers/amazon-organic-results-api/), [Amazon filters API](https://www.scrapingbee.com/scrapers/amazon-filters-api/), [Amazon related searches API](https://www.scrapingbee.com/scrapers/amazon-related-searches-api/), [Amazon spell check API](https://www.scrapingbee.com/scrapers/amazon-spell-check-api/), [Amazon zip code API](https://www.scrapingbee.com/scrapers/amazon-zip-code-api/).
|
|
105
|
+
|
|
106
|
+
### `product(asin, **params)`
|
|
107
|
+
|
|
108
|
+
`GET /api/v1/amazon/product`. **5 credits.**
|
|
109
|
+
|
|
110
|
+
**The wire parameter is `query`, not `asin`.** The value has to be a valid 10 character ASIN, but the field is named `query`. This client takes `asin` as its argument name and sends `query` for you.
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
detail = bee.product("B0GTMTZF3V")
|
|
114
|
+
detail["brand"] # 'Fitbit'
|
|
115
|
+
detail["price"] # 99.99
|
|
116
|
+
detail["currency"] # 'USD'
|
|
117
|
+
detail["rating"] # 4.3
|
|
118
|
+
detail["reviews_count"] # 2036
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The live response carried **56 top level keys**. The ones worth knowing:
|
|
122
|
+
|
|
123
|
+
| Field | Contents |
|
|
124
|
+
|---|---|
|
|
125
|
+
| `bullet_points` | The feature bullets, newline separated |
|
|
126
|
+
| `category` | A `ladder` of breadcrumb steps, each with `name` and `url` |
|
|
127
|
+
| `featured_merchant` | `name`, `seller_id`, `shipped_from`, `is_amazon_fulfilled` |
|
|
128
|
+
| `product_details` | Spec table as key and value pairs, including `best_sellers_rank` |
|
|
129
|
+
| `technical_details` | The second spec table |
|
|
130
|
+
| `rating_stars_distribution` | Review counts per star rating |
|
|
131
|
+
| `sales_rank` | Category rank entries |
|
|
132
|
+
| `variations` | Other sizes, colours and configurations |
|
|
133
|
+
| `images` | Image URLs |
|
|
134
|
+
| `delivery` | Delivery promises with type and date |
|
|
135
|
+
| `pricing_url` | The offer listing page for this ASIN |
|
|
136
|
+
| `parent_asin` | The variation parent |
|
|
137
|
+
| `discount_percentage`, `price_strikethrough`, `coupon` | Promotion state |
|
|
138
|
+
| `stock`, `max_quantity` | Availability |
|
|
139
|
+
|
|
140
|
+
Related: [Amazon ASIN API](https://www.scrapingbee.com/scrapers/amazon-asin-api/), [Amazon image API](https://www.scrapingbee.com/scrapers/amazon-image-api/), [Amazon review API](https://www.scrapingbee.com/scrapers/amazon-review-api/), [Amazon best sellers API](https://www.scrapingbee.com/scrapers/amazon-best-sellers-api/), [Amazon video results API](https://www.scrapingbee.com/scrapers/amazon-video-results-api/), [Amazon URL API](https://www.scrapingbee.com/scrapers/amazon-ulr-api/).
|
|
141
|
+
|
|
142
|
+
### `pricing(asin, **params)`
|
|
143
|
+
|
|
144
|
+
`GET /api/v1/amazon/pricing`. **5 credits.**
|
|
145
|
+
|
|
146
|
+
**This endpoint takes `asin` on the wire.** Search and product both take `query`. Pricing does not, and it rejects `query` explicitly:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{"errors": {"query": {"asin": ["Missing data for required field."], "query": ["Unknown field."]}}}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
That rejected call was billed **0 credits**, confirmed by `spb-cost: 0` on the response. This client raises `ScrapingBeeError` with the API's own error dict in `.payload`, so the offending field is never a guess.
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
offers = bee.pricing("B0GTMTZF3V")
|
|
156
|
+
for offer in offers["pricing"]:
|
|
157
|
+
print(offer["seller"], offer["price"], offer["condition"])
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Each offer carries `seller`, `seller_id`, `seller_link`, `condition`, `price`, `price_shipping`, `currency`, `rating_count` and a `delivery_options` list.
|
|
161
|
+
|
|
162
|
+
Related: [Amazon offers API](https://www.scrapingbee.com/scrapers/amazon-offers-api/), [Amazon seller API](https://www.scrapingbee.com/scrapers/amazon-seller-api/), [Amazon vendor API](https://www.scrapingbee.com/scrapers/amazon-vendor-api/), [Amazon shipping API](https://www.scrapingbee.com/scrapers/amazon-shipping-api/).
|
|
163
|
+
|
|
164
|
+
### `usage()`
|
|
165
|
+
|
|
166
|
+
`GET /api/v1/usage`. **Free.**
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
bee.usage()
|
|
170
|
+
# {'max_api_credit': 1000000, 'used_api_credit': 353946,
|
|
171
|
+
# 'max_concurrency': 100, 'current_concurrency': 0,
|
|
172
|
+
# 'renewal_subscription_date': '2026-09-21T12:06:28'}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Call this before a large run. Note it lags by minutes, so do not read it immediately afterwards to compute what a batch cost.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Placement helpers
|
|
180
|
+
|
|
181
|
+
Amazon search markup gives every card the same classes, so CSS selectors cannot tell a paid slot from an earned rank. The endpoint labels each result instead, which turns the problem into a filter.
|
|
182
|
+
|
|
183
|
+
Per product placement fields:
|
|
184
|
+
|
|
185
|
+
| Field | Type | Meaning |
|
|
186
|
+
|---|---|---|
|
|
187
|
+
| `is_sponsored` | bool | Paid placement |
|
|
188
|
+
| `sponsored_position` | int or None | Rank among the ads |
|
|
189
|
+
| `organic_position` | int or None | Rank among earned results |
|
|
190
|
+
| `is_amazons_choice` | bool | Amazon's Choice badge |
|
|
191
|
+
| `best_seller` | bool | Best Seller badge |
|
|
192
|
+
| `sales_volume` | str | For example `10K+ bought in past month` |
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
page = bee.search("fitness tracker", sort_by="featured")
|
|
196
|
+
|
|
197
|
+
AmazonScraper.featured(page) # sponsored, ordered by ad slot
|
|
198
|
+
AmazonScraper.organic(page) # earned, ordered by organic rank
|
|
199
|
+
AmazonScraper.badged(page) # Amazon's Choice or Best Seller
|
|
200
|
+
AmazonScraper.facets(page) # the refinements object
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Two live runs on the same query returned 7 featured of 24 products, then 9 of 26. Paid density moves between requests, so measure it rather than assuming a fixed ratio.
|
|
204
|
+
|
|
205
|
+
`is_prime` came back `False` on every row of both pages, so verify it against your own target category before building a Prime filter on it.
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Credit cost
|
|
210
|
+
|
|
211
|
+
Measured from `spb-cost` response headers, not quoted from a pricing page. This client stores the value on `bee.last_cost` after every call.
|
|
212
|
+
|
|
213
|
+
| Call | Credits |
|
|
214
|
+
|---|---|
|
|
215
|
+
| Search, default light request | 5 per page |
|
|
216
|
+
| Search, `light_request=False` | 15 per page |
|
|
217
|
+
| Product, default | 5 |
|
|
218
|
+
| Product, `light_request=False` | 15 |
|
|
219
|
+
| Pricing | 5 |
|
|
220
|
+
| Any screenshot | 15 |
|
|
221
|
+
| Rejected request | 0 |
|
|
222
|
+
| `usage()` | 0 |
|
|
223
|
+
|
|
224
|
+
Light requests skip the browser. They were sufficient for search, product and pricing on every call made here. Turn them off when you need review text or other content that appears only after JavaScript runs.
|
|
225
|
+
|
|
226
|
+
Failed requests are retried inside the API for up to 30 seconds, so set client timeouts above that. This client defaults to 60 seconds.
|
|
227
|
+
|
|
228
|
+
Plan tiers: [ScrapingBee pricing](https://www.scrapingbee.com/pricing).
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Scope
|
|
233
|
+
|
|
234
|
+
Public Amazon listing and product pages. Nothing in this package signs in, and scraping under login credentials is prohibited by ScrapingBee's terms of service.
|
|
235
|
+
|
|
236
|
+
## Related features
|
|
237
|
+
|
|
238
|
+
[AI web scraping](https://www.scrapingbee.com/features/ai-web-scraping-api/), [data extraction rules](https://www.scrapingbee.com/features/data-extraction/), [Amazon feature page](https://www.scrapingbee.com/features/amazon/), [screenshots](https://www.scrapingbee.com/features/screenshot/), [markdown scraper](https://www.scrapingbee.com/features/markdown-scraper/), [Make integration](https://www.scrapingbee.com/features/make/), [n8n integration](https://www.scrapingbee.com/features/n8n/), [Zapier integration](https://www.scrapingbee.com/features/zapier/).
|
|
239
|
+
|
|
240
|
+
The no code version of this workflow, with the Make scenario and the extraction rules, is at [github.com/ScrapingBee/nocode-amazon](https://github.com/ScrapingBee/nocode-amazon).
|
|
241
|
+
|
|
242
|
+
## License
|
|
243
|
+
|
|
244
|
+
MIT
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
pyproject.toml
|
|
5
|
+
src/nocode_amazon/__init__.py
|
|
6
|
+
src/nocode_amazon/client.py
|
|
7
|
+
src/nocode_amazon.egg-info/PKG-INFO
|
|
8
|
+
src/nocode_amazon.egg-info/SOURCES.txt
|
|
9
|
+
src/nocode_amazon.egg-info/dependency_links.txt
|
|
10
|
+
src/nocode_amazon.egg-info/requires.txt
|
|
11
|
+
src/nocode_amazon.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
requests>=2.25.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
nocode_amazon
|