如何在Python中高效程序化获取Facebook测试用户访问令牌?
Got it, I’ve run into this exact pagination slog with Facebook’s Graph API before—nothing’s more frustrating than waiting 5+ minutes just to pull test user data. Let’s walk through the most effective fixes to speed this up in Python.
1. Crank Up the Page Limit First
The default 25 results per page is tiny, and that’s probably the biggest culprit here. Facebook’s Graph API lets you bump this up to 1000 results per page for most endpoints (including the test users endpoint) using the limit parameter.
Just modify your request URL to:
https://graph.facebook.com/{app-id}/accounts/test-users?access_token={app-id}|{app-secret}&limit=1000
This cuts the number of pages you need to fetch by 40x right off the bat. I’ve used this to reduce a 40-page job down to 1 page for apps with <1000 test users—total game changer.
2. Use Batch Requests to Cut Down HTTP Overhead
If you still have multiple pages after setting limit=1000, batch requests let you fetch multiple pages in a single HTTP call, eliminating the overhead of opening/closing connections for every page.
Here’s a Python example using the requests library:
import requests APP_ID = "your-app-id" APP_SECRET = "your-app-secret" BASE_URL = f"https://graph.facebook.com/{APP_ID}/accounts/test-users" ACCESS_TOKEN = f"{APP_ID}|{APP_SECRET}" def fetch_all_test_users(): # First get the initial page to check for pagination initial_response = requests.get(BASE_URL, params={"access_token": ACCESS_TOKEN, "limit": 1000}).json() all_users = initial_response.get("data", []) next_pages = [] # Collect all next page URLs from the initial response next_url = initial_response.get("paging", {}).get("next") while next_url: next_pages.append(next_url) # Get the next page's pagination link temp_response = requests.get(next_url).json() next_url = temp_response.get("paging", {}).get("next") # Create batch requests for all remaining pages batch_requests = [{"method": "GET", "relative_url": next_url.split("graph.facebook.com")[1]} for next_url in next_pages] batch_response = requests.post( f"https://graph.facebook.com/{APP_ID}", params={"access_token": ACCESS_TOKEN, "batch": str(batch_requests)} ).json() # Parse batch results for resp in batch_response: if resp.get("code") == 200: page_data = requests.utils.json.loads(resp["body"]) all_users.extend(page_data.get("data", [])) # Extract all access tokens all_access_tokens = [user["access_token"] for user in all_users if "access_token" in user] return all_access_tokens
Pro tip: Keep batch sizes under 50 requests per batch—Facebook has a hard limit on batch request size, and going over will throw errors.
3. Async HTTP for Concurrent Pagination
If batch requests aren’t enough (or you prefer async code), use aiohttp to fetch multiple pages concurrently instead of waiting for each page to finish before starting the next. This is especially useful if you have dozens of pages to pull.
Here’s a quick example:
import aiohttp import asyncio APP_ID = "your-app-id" APP_SECRET = "your-app-secret" ACCESS_TOKEN = f"{APP_ID}|{APP_SECRET}" async def fetch_page(session, url): async with session.get(url) as resp: return await resp.json() async def fetch_all_test_users_async(): initial_url = f"https://graph.facebook.com/{APP_ID}/accounts/test-users?access_token={ACCESS_TOKEN}&limit=1000" session = aiohttp.ClientSession() initial_data = await fetch_page(session, initial_url) all_users = initial_data.get("data", []) page_urls = [] # Collect all next page URLs next_url = initial_data.get("paging", {}).get("next") while next_url: page_urls.append(next_url) temp_data = await fetch_page(session, next_url) next_url = temp_data.get("paging", {}).get("next") # Fetch all pages concurrently tasks = [fetch_page(session, url) for url in page_urls] pages_data = await asyncio.gather(*tasks) # Combine results for page in pages_data: all_users.extend(page.get("data", [])) await session.close() return [user["access_token"] for user in all_users if "access_token" in user] # Run the async function if __name__ == "__main__": tokens = asyncio.run(fetch_all_test_users_async()) print(f"Fetched {len(tokens)} access tokens")
Note: Don’t forget to handle rate limiting here! Facebook will return a 429 status code if you hit your API quota. Add a retry mechanism with exponential backoff (like the tenacity library) to avoid getting blocked.
4. Cache & Incremental Updates to Avoid Full Scans
If you don’t need to fetch all test users every time, use the since parameter to only pull users created after your last fetch. Store the timestamp of your last run, then add since={last_timestamp} to your request URL. This way you only fetch new users instead of reprocessing the entire list every time.
Key Things to Watch Out For
- Rate Limiting: Always check the
x-app-usageresponse header to monitor your API quota. If you hit a 429 error, implement exponential backoff before retrying. - Token Expiry: Test user access tokens do expire—make sure you’re fetching fresh ones when needed, or use the
access_tokenfrom the response directly instead of caching it long-term.
内容的提问来源于stack exchange,提问作者Mochi Bear




