You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
### Description
- This PR updates the SDK to work with `apify-python-client` v3, which
introduces fully typed API clients generated from OpenAPI
specifications.
- See apify/apify-client-python#604 for more
details.
### Issues
- Closes: #736
- Closes: #770
- Closes: #697
- Closes: #853
### Testing
- The existing SDK tests pass with `apify-python-client` v3.
Copy file name to clipboardExpand all lines: .rules.md
+6-5Lines changed: 6 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ This file provides guidance to programming agents when working with code in this
4
4
5
5
## Project Overview
6
6
7
-
The Apify SDK for Python (`apify` package on PyPI) is the official library for creating [Apify Actors](https://docs.apify.com/platform/actors) in Python. It provides Actor lifecycle management, storage access (datasets, key-value stores, request queues), event handling, proxy configuration, and pay-per-event charging. It builds on top of the [Crawlee](https://crawlee.dev/python) web scraping framework and the [Apify API Client](https://docs.apify.com/api/client/python). Supports Python 3.10–3.14. Build system: hatchling.
7
+
The Apify SDK for Python (`apify` package on PyPI) is the official library for creating [Apify Actors](https://docs.apify.com/platform/actors) in Python. It provides Actor lifecycle management, storage access (datasets, key-value stores, request queues), event handling, proxy configuration, and pay-per-event charging. It builds on top of the [Crawlee](https://crawlee.dev/python) web scraping framework and the [Apify API Client](https://docs.apify.com/api/client/python). Supports Python 3.11–3.14. Build system: hatchling.
8
8
9
9
## Common Commands
10
10
@@ -46,7 +46,7 @@ uv run poe e2e-tests
46
46
## Code Style
47
47
48
48
-**Formatter/Linter**: Ruff (line length 120, single quotes for inline, double quotes for docstrings)
49
-
-**Type checker**: ty (targets Python 3.10)
49
+
-**Type checker**: ty (targets Python 3.11)
50
50
-**All ruff rules enabled** with specific ignores — see `pyproject.toml``[tool.ruff.lint]` for the full ignore list
51
51
- Tests are exempt from docstring rules (`D`), assert warnings (`S101`), and private member access (`SLF001`)
52
52
- Unused imports are allowed in `__init__.py` files (re-exports)
-**`_models.py`** — Pydantic models for API data structures (Actor runs, webhooks, pricing info, etc.).
74
+
-**`_webhook.py`** — The `Webhook` dataclass (ad-hoc / persistent webhook definition) and the `to_client_representations` helper. Response and data models are no longer defined in the SDK — they come from `apify-client` v3 (e.g. `Run`, the Actor pricing-info models).
-**`crawlee`** — Base framework providing storage abstractions, event system, configuration, service locator pattern
104
-
-**`apify-client`** — HTTP client for the Apify API (`ApifyClientAsync`)
105
-
-**`apify-shared`** — Shared constants and utilities (`ApifyEnvVars`, `ActorEnvVars`, etc.)
104
+
-**`apify-client`** — HTTP client for the Apify API (`ApifyClientAsync`); also the source of response and data models (`Run`, pricing info, webhook representations)
105
+
106
+
The SDK no longer depends on `apify-shared`. The platform env-var enums (`ApifyEnvVars`, `ActorEnvVars`) are vendored in `apify._consts` and re-exported from the top-level `apify` package.
Copy file name to clipboardExpand all lines: docs/04_upgrading/upgrading_to_v4.md
+130Lines changed: 130 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -68,3 +68,133 @@ run = await Actor.call('user/actor', timeout='inherit')
68
68
The deprecated `latest_sdk_version`, `log_format`, and `standby_port` fields have been removed from `Configuration`:
69
69
- In place of `standby_port`, use `web_server_port`.
70
70
-`latest_sdk_version` and `log_format` don't have replacement. SDK version checking isn't supported for the Python SDK and the log format should be adjusted in code instead.
71
+
72
+
## Built on `apify-client` v3
73
+
74
+
The SDK is now built on [`apify-client`](https://docs.apify.com/api/client/python) v3 and no longer depends on `apify-shared`. The sections below cover the user-visible consequences; see the client's [Upgrading to v3](https://docs.apify.com/api/client/python/docs/upgrading/upgrading-to-v3) guide for the full list of changes in the client itself.
75
+
76
+
### Environment variable enums moved
77
+
78
+
If you imported the platform environment-variable enums from `apify_shared.consts` (`ApifyEnvVars`, `ActorEnvVars`), import them from `apify` instead — they are now vendored in the SDK and re-exported from the top-level package.
79
+
80
+
```python
81
+
# Before (v3)
82
+
from apify_shared.consts import ApifyEnvVars
83
+
84
+
# After (v4)
85
+
from apify import ApifyEnvVars
86
+
```
87
+
88
+
## Typed responses
89
+
90
+
`Actor.start`, `Actor.abort`, `Actor.call`, and `Actor.call_task` now return `apify_client._models.Run` instead of the SDK-side `ActorRun`. Both are [Pydantic](https://docs.pydantic.dev/latest/) models with the same snake_case fields, so field access is unchanged — only the type and import path differ. The SDK no longer ships its own response models (`apify._models` has been removed); response shapes come from `apify-client`.
91
+
92
+
## Literal string aliases instead of StrEnum classes
93
+
94
+
Generated enum-like types are now [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal) string aliases instead of `StrEnum` classes. Pass plain strings instead of enum members.
95
+
96
+
-`apify.WebhookEventType` is now a `Literal[...]` instead of a `StrEnum`. Use plain string values (`'ACTOR.RUN.FAILED'`) instead of enum members.
97
+
-`apify_shared.consts.ActorEventTypes` (a `StrEnum`) is replaced by `apify.ActorEventTypes`, now a `Literal['systemInfo', 'persistState', 'migrating', 'aborting']`. For runtime values, use `apify.Event` (re-exported from Crawlee) instead of enum members.
98
+
99
+
```python
100
+
# Before (v3)
101
+
from apify import Actor
102
+
from apify_shared.consts import ActorEventTypes
103
+
104
+
Actor.on(ActorEventTypes.SYSTEM_INFO, callback)
105
+
106
+
# After (v4)
107
+
from apify import Actor, Event
108
+
109
+
Actor.on(Event.SYSTEM_INFO, callback)
110
+
```
111
+
112
+
## Actor pricing info models
113
+
114
+
The Actor pricing-info models exposed through `Actor.configuration.actor_pricing_info` — `FreeActorPricingInfo`, `FlatPricePerMonthActorPricingInfo`, `PricePerDatasetItemActorPricingInfo`, `PayPerEventActorPricingInfo`, and the nested `ActorChargeEvent` / `PricingPerEvent` — are now thin subclasses of the corresponding `apify-client` models instead of standalone SDK copies. The discriminated-union shape is unchanged, so existing access (`pricing_model`, per-event titles and prices) keeps working; the models now expose the full `apify-client` field set, and a charge event's `event_price_usd` is optional (it is unset for tier-priced events). `ChargingManager.get_pricing_info()` is unchanged.
115
+
116
+
## `Webhook` API simplified
117
+
118
+
The `Webhook` model has been slimmed down to only the fields a user sets when defining a webhook. Server-populated response fields (`id`, `created_at`, `modified_at`, `user_id`, `is_ad_hoc`, `condition`, `last_dispatch`, `stats`) and the unused `WebhookCondition` helper class have been removed. The `description` and `should_interpolate_strings` fields have also been removed — they are not part of the ad-hoc webhook representation (`event_types`, `request_url`, `payload_template`, `headers_template`) that `Actor.start` / `Actor.call` / `Actor.call_task` and `Actor.add_webhook` now send. `Webhook` is now a plain `@dataclass` instead of a Pydantic `BaseModel` — construct it with snake_case kwargs; `.model_dump()` / `.model_validate()` are gone.
119
+
120
+
The retry and idempotency kwargs that used to live on `Actor.add_webhook` have moved onto the `Webhook` instance itself.
The `idempotency_key` kwarg form on `Actor.add_webhook` still works for one more release but emits a `DeprecationWarning` and will be removed in v5.0. The `ignore_ssl_errors` and `do_not_retry` kwargs have been removed outright — set them on the `Webhook` instance.
148
+
149
+
`apify.WebhookCondition` is no longer exported; the SDK now binds the webhook to the current Actor run internally.
150
+
151
+
The `webhooks` argument on `Actor.start`, `Actor.call`, and `Actor.call_task` still accepts `list[Webhook]` and the fields used at the call site (`event_types`, `request_url`, `payload_template`, `headers_template`) are unchanged.
152
+
153
+
## `Actor.new_client` — `timeout` scales all tiers
154
+
155
+
`apify-client` v3 split its single timeout into four tiers (short / medium / long / max). `Actor.new_client(timeout=...)` still takes a single `timedelta`; the SDK uses it as the medium-tier baseline and scales the other tiers proportionally (short = `timeout / 6`, long = `timeout * 12`, max = `timeout * 12`). The public signature is unchanged — no migration needed.
156
+
157
+
## Using the client from `Actor.new_client`
158
+
159
+
`Actor.new_client()` (and the `Actor.apify_client` property) now returns an `apify-client` v3 `ApifyClientAsync`. When you use that client directly, the client's v3 breaking changes apply — the most impactful ones are below. See the client's [Upgrading to v3](https://docs.apify.com/api/client/python/docs/upgrading/upgrading-to-v3) guide for the complete reference.
160
+
161
+
### 404 raises `NotFoundError` on ambiguous endpoints
162
+
163
+
Direct `.get(id)` and `.delete(id)` calls still swallow 404 into `None`. But where a 404 could mean either the parent or the sub-resource is missing, the client now raises `NotFoundError` instead of returning `None`.
### Async `iterate_*` are no longer coroutine functions
199
+
200
+
`DatasetClientAsync.iterate_items()` and `KeyValueStoreClientAsync.iterate_keys()` are now plain `def` functions returning `AsyncIterator[T]`. Consumer code (`async for ...`) is unchanged; if you annotate the call's return value, change `AsyncGenerator[T, None]` to `AsyncIterator[T]`.
0 commit comments