cloudflare-python icon indicating copy to clipboard operation
cloudflare-python copied to clipboard

Pagination on /accounts returns only one page, but has_more_pages() incorrectly returns True

Open adragojlovic opened this issue 10 months ago • 2 comments

Describe the bug

I created an account-scoped API token and used it to call the /accounts endpoint, expecting to retrieve a single account (as expected for an account-scoped token).

Here is the code I am using:

cloudflare_client = Cloudflare(api_token=cloudflare_integration_config.api_token)
for cloudflare_client_result in cloudflare_client.accounts.list():
    ...

However the loop keeps returning the same single account result repeatedly.

After debugging, I found that has_next_page() always returns True, even though there’s only one result. This causes the pagination loop to continue indefinitely.

ipdb> cloudflare_client_result
SyncV4PagePaginationArray[Account](result=[Account(id='ACCOUNT_ID', name="ACCOUNT_NAME", created_on=datetime.datetime(2023, 2, 8, 7, 11, 56, 234700, tzinfo=TzInfo(UTC)), settings=Settings(abuse_contact_email=None, default_nameservers='cloudflare.standard', enforce_twofactor=False, use_account_custom_ns_by_default=False, api_access_enabled=None, access_approval_expiry=None), type='standard', legacy_flags={'enterprise_zone_quota': {'maximum': 0, 'current': 0, 'available': 0}})], result_info=V4PagePaginationArrayResultInfo(page=1, per_page=20, total_pages=1, count=1, total_count=1), success=True, errors=[], messages=[])

ipdb> cloudflare_client_result.has_next_page()
True

UPDATE:

➜  curl -X GET "https://api.cloudflare.com/client/v4/accounts?per_page=50&page=1" \
     -H "Authorization: Bearer MY_API_KEY" \
     -H "Content-Type:application/json"

{"result":[{"id":"ACCOUNT_ID_1","name":"ACCOUNT_NAME_1","type":"standard","settings":{"enforce_twofactor":false,"api_access_enabled":null,"access_approval_expiry":null,"use_account_custom_ns_by_default":false,"default_nameservers":"cloudflare.standard","abuse_contact_email":null},"legacy_flags":{"enterprise_zone_quota":{"maximum":0,"current":0,"available":0}},"created_on":"2023-02-08T07:11:56.234700Z"}],"result_info":{"page":1,"per_page":50,"total_pages":1,"count":1,"total_count":1},"success":true,"errors":[],"messages":[]}%


➜  curl -X GET "https://api.cloudflare.com/client/v4/accounts?per_page=50&page=2" \
     -H "Authorization: Bearer MY_API_KEY" \
     -H "Content-Type:application/json"

{"result":[{"id":"ACCOUNT_ID_1","name":"ACCOUNT_NAME_1","type":"standard","settings":{"enforce_twofactor":false,"api_access_enabled":null,"access_approval_expiry":null,"use_account_custom_ns_by_default":false,"default_nameservers":"cloudflare.standard","abuse_contact_email":null},"legacy_flags":{"enterprise_zone_quota":{"maximum":0,"current":0,"available":0}},"created_on":"2023-02-08T07:11:56.234700Z"}],"result_info":{"page":2,"per_page":50,"total_pages":1,"count":1,"total_count":1},"success":true,"errors":[],"messages":[]}%


➜  curl -X GET "https://api.cloudflare.com/client/v4/accounts?per_page=50&page=3" \
     -H "Authorization: Bearer MY_API_KEY" \
     -H "Content-Type:application/json"

{"result":[{"id":"ACCOUNT_ID_1","name":"ACCOUNT_NAME_1","type":"standard","settings":{"enforce_twofactor":false,"api_access_enabled":null,"access_approval_expiry":null,"use_account_custom_ns_by_default":false,"default_nameservers":"cloudflare.standard","abuse_contact_email":null},"legacy_flags":{"enterprise_zone_quota":{"maximum":0,"current":0,"available":0}},"created_on":"2023-02-08T07:11:56.234700Z"}],"result_info":{"page":3,"per_page":50,"total_pages":1,"count":1,"total_count":1},"success":true,"errors":[],"messages":[]}%

It appears that the page query parameter is not functioning as described in the API documentation.

To Reproduce

  1. Issue an account-scoped API token from Cloudflare.
  2. Use the token to call the /accounts endpoint using the API client.
  3. Attempt to fetch all accounts and append results to a list.
  4. On the first (and should be the only but it's not) page of results, check has_next_page().
  5. Observe that has_next_page() returns True, even though there are no additional pages.

Code snippets

results = []
cloudflare_client = Cloudflare(api_token=cloudflare_integration_config.api_token)
for cloudflare_client_result in cloudflare_client.accounts.list().iter_pages():
    breakpoint()
    results.append(cloudflare_client_result)
pprint(results)
results = []
cloudflare_client = Cloudflare(api_token=cloudflare_integration_config.api_token)
for cloudflare_client_result in cloudflare_client.accounts.list():
    pprint(cloudflare_client_result)
    results.append(cloudflare_client_result)

OS

macOS 15.3.2 (24D81)

Python version

3.12.9

Library version

4.1.0

adragojlovic avatar Apr 01 '25 08:04 adragojlovic

Confirming that I'm seeing the same thing in linux; just keeps printing the same account again and again, seemingly forever

BryanConradHart avatar Jun 22 '25 05:06 BryanConradHart

We fixed something along these lines for Go last week. @vaishakdinesh to check if it works here as well. Thanks!

jhutchings1 avatar Jun 30 '25 21:06 jhutchings1