Grailed.com自动关注商品失败求助:POST请求无报错但未生效
Great question! Let's walk through why your follow request isn't working and how to fix it—since you already got login working, we're halfway there.
Common Issues & Fixes
1. Your Payload is Missing a Critical Field
Grailed's /api/follows endpoint almost certainly requires more than just an id—it needs to know what type of object you're following (a listing, user, etc.). When you manually click "Follow" on a product page, check your browser's DevTools (Network tab) for the POST request to /api/follows—you'll see the payload looks like this:
{ "followable_id": "7917017", "followable_type": "Listing" }
Your original code only sends "id": "7917017"—the server doesn't know if you're trying to follow a listing, a user, or something else, so it ignores the request without throwing an error.
2. Hardcoded CSRF Token is Probably Stale
You're using a static x-csrf-token value, but Grailed updates this token after login (and on page loads). Hardcoding it means your request uses an invalid token, even if login succeeded. Instead, dynamically extract the token from either:
- The login response cookies (look for
_grailed_sessionor acsrf-tokencookie) - The product page's meta tags (visit the listing page first, then scrape the
<meta name="csrf-token" content="...">tag)
3. Missing Headers That Signal "Human" Behavior
Grailed's anti-bot systems look for headers that mimic real browser traffic. Your original headers are missing or hardcoded values that should be dynamic:
- Referer: Always include the product page URL to show you navigated there before clicking follow
- X-Amplitude-ID: This is a user-specific tracking ID generated by JavaScript—if you're using
requests, you might need to extract it from the product page's JS, or skip it (some sites ignore it if other headers are correct) - Reuse your session's headers consistently (don't overwrite the entire headers dict for the follow request—just add/modify what's needed)
4. Skipping "Human" Navigation Steps
Anti-bot systems flag requests that jump straight to API calls without browsing the site first. Before sending the follow request, make sure to:
- Visit the product page with your logged-in session
- Let the server set any necessary cookies or tracking parameters
Fixed Code Example (Using Requests)
import requests from bs4 import BeautifulSoup # Initialize session with a consistent user-agent session = requests.Session() session.headers.update({ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36' }) # Step 1: Login (use your existing login logic, keep the session) login_data = { "user": {"email": "your_email@example.com", "password": "your_password"} } login_response = session.post("https://www.grailed.com/api/sign_in", json=login_data) login_response.raise_for_status() # Ensure login succeeded # Step 2: Visit the product page to get fresh CSRF token and simulate navigation product_id = "7917017" product_url = f"https://www.grailed.com/listings/{product_id}" product_page = session.get(product_url) product_page.raise_for_status() # Extract CSRF token from page meta tags soup = BeautifulSoup(product_page.content, "html.parser") csrf_token = soup.find("meta", {"name": "csrf-token"})["content"] # Step 3: Prepare follow request headers (only add what's needed) follow_headers = { "Accept": "application/json", "Content-Type": "application/json", "X-CSRF-Token": csrf_token, "X-Api-Version": "application/grailed.api.v1", "Referer": product_url, "Origin": "https://www.grailed.com" } # Step 4: Use the correct payload structure follow_payload = { "followable_id": product_id, "followable_type": "Listing" } # Step 5: Send the follow request follow_response = session.post( "https://www.grailed.com/api/follows", json=follow_payload, headers=follow_headers ) # Debug: Check response status and content print(f"Response Status: {follow_response.status_code}") print(f"Response JSON: {follow_response.json()}")
If Requests Still Fails: Try Browser Automation
If Grailed's anti-bot systems are blocking your requests (even with the fixes above), you'll need to simulate a real browser with tools like Selenium or Playwright. These tools execute JavaScript, mimic human clicks, and are harder to detect:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import time # Initialize Chrome browser driver = webdriver.Chrome() driver.get("https://www.grailed.com/login") # Login manually (or automate filling fields) email_input = driver.find_element(By.ID, "user_email") password_input = driver.find_element(By.ID, "user_password") email_input.send_keys("your_email@example.com") password_input.send_keys("your_password") login_button = driver.find_element(By.NAME, "commit") login_button.click() # Wait for login to complete time.sleep(2) # Navigate to the product page product_url = "https://www.grailed.com/listings/7917017" driver.get(product_url) # Wait for the follow button to load and click it follow_button = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, "button[data-testid='follow-button']")) ) follow_button.click() # Verify success (check if button text changes to "Following") time.sleep(1) print(f"Follow button state: {follow_button.text}") driver.quit()
Final Notes
- Always check the actual request payload/headers in your browser's DevTools—this is the best way to match what a real user sends.
- Grailed doesn't have a public API, so you're relying on reverse-engineering their private API—be aware that endpoints can change at any time.
- Avoid sending too many requests too quickly—rate limiting is another common anti-bot measure.
内容的提问来源于stack exchange,提问作者Kunwar Sodhi

