# Mealie Batch Recipe Import

Authenticate via API and bulk-import recipes from URLs. Mealie's built-in scraper handles ~300+ sites but reliability varies wildly.

## API Auth Pattern

```python
import requests

MEALIE = "http://127.0.0.1:9925"  # or https://grajmedia.duckdns.org:3449

resp = requests.post(
    f"{MEALIE}/api/auth/token",
    data={"username": "email@example.com", "password": "password", "grant_type": ""},
    headers={"Content-Type": "application/x-www-form-urlencoded"}
)
token = resp.json()["access_token"]
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
```

## Batch Import

```python
urls = ["https://example.com/recipe-1", "https://example.com/recipe-2"]

for url in urls:
    resp = requests.post(
        f"{MEALIE}/api/recipes/create/url",
        json={"url": url},
        headers=headers,
        timeout=60
    )
    # 200/201 = success, 400 = scraper failed
```

## Scraper Reliability (as of June 2026)

| Site | Reliability | Notes |
|---|---|---|
| BBC Good Food | High | Consistently works |
| RecipeTin Eats | High | Good parser support |
| Budget Bytes | Medium | HTTPException ~30% of the time, retry helps |
| Damn Delicious | Medium | Intermittent blocks |
| AllRecipes | Low | Frequently blocked (Cloudflare) |
| Simply Recipes | Low | Frequently blocked |
| Gimme Some Oven | Low | Frequently blocked |

Add `time.sleep(1.5)` between requests to avoid rate limiting.

## URL Format

The `/api/recipes/create/url` endpoint expects a full recipe page URL. It does NOT accept search results, category pages, or non-recipe URLs. The scraper extracts title, ingredients, steps, image, and metadata automatically.
