From 10c903dc620ef13eaaa51b14608a51865520d612 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 4 Nov 2026 14:24:25 +0100 Subject: [PATCH 1/3] fix: use the configured public API URL in `Actor.new_client` --- src/apify/_actor.py | 9 +++++++-- tests/unit/actor/test_actor_helpers.py | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/apify/_actor.py b/src/apify/_actor.py index 9a1382d2..69019f7e 100644 --- a/src/apify/_actor.py +++ b/src/apify/_actor.py @@ -597,6 +597,7 @@ def new_client( *, token: str | None = None, api_url: str | None = None, + api_public_url: str | None = None, max_retries: int | None = None, min_delay_between_retries: timedelta | None = None, timeout: timedelta | None = None, @@ -604,8 +605,8 @@ def new_client( """Return a new instance of the Apify API client. The `ApifyClientAsync` class is provided by the [apify-client](https://github.com/apify/apify-client-python) - package, and it is automatically configured using the `APIFY_API_BASE_URL` and `APIFY_TOKEN` environment - variables. + package, and it is automatically configured using the `APIFY_API_BASE_URL`, `APIFY_API_PUBLIC_BASE_URL` and + `APIFY_TOKEN` environment variables. You can override the token via the available options. That's useful if you want to use the client as a different Apify user than the SDK internals are using. @@ -613,6 +614,9 @@ def new_client( Args: token: The Apify API token. api_url: The URL of the Apify API server to which to connect to. Defaults to https://api.apify.com. + api_public_url: The globally accessible URL of the Apify API server, used to build public URLs of + resources. Defaults to the `APIFY_API_PUBLIC_BASE_URL` environment variable, or to + https://api.apify.com when it is not set. max_retries: How many times to retry a failed request at most. min_delay_between_retries: How long will the client wait between retrying requests (increases exponentially from this value). @@ -626,6 +630,7 @@ def new_client( client_kwargs: dict[str, Any] = { 'token': token or self.configuration.token, 'api_url': api_url or self.configuration.api_base_url, + 'api_public_url': api_public_url or self.configuration.api_public_base_url, 'compression': 'brotli', } if max_retries is not None: diff --git a/tests/unit/actor/test_actor_helpers.py b/tests/unit/actor/test_actor_helpers.py index e8b0d8f9..267c412d 100644 --- a/tests/unit/actor/test_actor_helpers.py +++ b/tests/unit/actor/test_actor_helpers.py @@ -12,6 +12,7 @@ from apify_client import ApifyClientAsync from apify_client._models import Run +from apify_client._resource_clients import KeyValueStoreClientAsync from crawlee.events._types import Event from apify import Actor, Webhook @@ -85,6 +86,25 @@ async def test_new_client_config_creation(monkeypatch: pytest.MonkeyPatch) -> No await my_actor.exit() +async def test_new_client_uses_configured_api_public_base_url(monkeypatch: pytest.MonkeyPatch) -> None: + """`new_client` builds public URLs on the configured `api_public_base_url` host.""" + monkeypatch.setenv(ApifyEnvVars.API_BASE_URL, 'http://internal-api.example.com') + monkeypatch.setenv(ApifyEnvVars.API_PUBLIC_BASE_URL, 'https://public-api.example.com') + monkeypatch.setattr(KeyValueStoreClientAsync, 'get', AsyncMock(return_value=None)) + my_actor = _ActorType() + await my_actor.init() + + client = my_actor.new_client() + public_url = await client.key_value_store('store-id').get_record_public_url('key') + assert public_url == 'https://public-api.example.com/v2/key-value-stores/store-id/records/key' + + client_with_override = my_actor.new_client(api_public_url='https://override.example.com') + public_url = await client_with_override.key_value_store('store-id').get_record_public_url('key') + assert public_url == 'https://override.example.com/v2/key-value-stores/store-id/records/key' + + await my_actor.exit() + + async def test_call_actor(apify_client_async_patcher: ApifyClientAsyncPatcher, fake_actor_run: Run) -> None: apify_client_async_patcher.patch('actor', 'call', return_value=fake_actor_run) actor_id = 'some-actor-id' From 90de6c84bbf1dec700de6e5a748536018216bdeb Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 4 Nov 2026 14:36:04 +0100 Subject: [PATCH 2/3] docs: mention `api_public_url` in the `Actor.new_client` docs --- docs/02_concepts/08_access_apify_api.mdx | 2 +- src/apify/_actor.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/02_concepts/08_access_apify_api.mdx b/docs/02_concepts/08_access_apify_api.mdx index 774002bc..94868bd3 100644 --- a/docs/02_concepts/08_access_apify_api.mdx +++ b/docs/02_concepts/08_access_apify_api.mdx @@ -28,7 +28,7 @@ You select a resource with the matching method (for example, `Actor.apify_client ## Actor new client -To create a completely new instance of the client (for example, to use a different user's token or change the client configuration), use the `Actor.new_client` method. It accepts an optional `token` and `api_url`, along with retry and timeout settings (`max_retries`, `min_delay_between_retries`, `timeout`), and returns a fresh `ApifyClientAsync`: +To create a completely new instance of the client (for example, to use a different user's token or change the client configuration), use the `Actor.new_client` method. It accepts an optional `token`, `api_url`, and `api_public_url`, along with retry and timeout settings (`max_retries`, `min_delay_between_retries`, `timeout`), and returns a fresh `ApifyClientAsync`: {ActorNewClientExample} diff --git a/src/apify/_actor.py b/src/apify/_actor.py index 69019f7e..e28c20d8 100644 --- a/src/apify/_actor.py +++ b/src/apify/_actor.py @@ -614,9 +614,9 @@ def new_client( Args: token: The Apify API token. api_url: The URL of the Apify API server to which to connect to. Defaults to https://api.apify.com. - api_public_url: The globally accessible URL of the Apify API server, used to build public URLs of - resources. Defaults to the `APIFY_API_PUBLIC_BASE_URL` environment variable, or to - https://api.apify.com when it is not set. + api_public_url: The globally accessible URL of the Apify API server, used to build public URLs of resources. + Defaults to the `APIFY_API_PUBLIC_BASE_URL` environment variable, or to https://api.apify.com when it + is not set. max_retries: How many times to retry a failed request at most. min_delay_between_retries: How long will the client wait between retrying requests (increases exponentially from this value). From 6477825c52fa3d601ee87b76c404996ab9de3a09 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 4 Nov 2026 14:42:32 +0100 Subject: [PATCH 3/3] docs: name the env var defaults of `Actor.new_client` URL params --- src/apify/_actor.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/apify/_actor.py b/src/apify/_actor.py index e28c20d8..526146cf 100644 --- a/src/apify/_actor.py +++ b/src/apify/_actor.py @@ -613,10 +613,10 @@ def new_client( Args: token: The Apify API token. - api_url: The URL of the Apify API server to which to connect to. Defaults to https://api.apify.com. + api_url: The URL of the Apify API server to which to connect to. Defaults to the `APIFY_API_BASE_URL` + environment variable. api_public_url: The globally accessible URL of the Apify API server, used to build public URLs of resources. - Defaults to the `APIFY_API_PUBLIC_BASE_URL` environment variable, or to https://api.apify.com when it - is not set. + Defaults to the `APIFY_API_PUBLIC_BASE_URL` environment variable. max_retries: How many times to retry a failed request at most. min_delay_between_retries: How long will the client wait between retrying requests (increases exponentially from this value).