| Crates.io | anylist_rs |
| lib.rs | anylist_rs |
| version | 0.4.0 |
| created_at | 2026-01-15 23:03:21.790798+00 |
| updated_at | 2026-01-25 07:50:28.303627+00 |
| description | Interact with the grocery list management app AnyList's undocumented API. Unofficial. |
| homepage | https://github.com/phildenhoff/anylist_rs |
| repository | https://github.com/phildenhoff/anylist_rs |
| max_upload_size | |
| id | 2047316 |
| size | 311,439 |
A Rust crate for interacting with the grocery list management app AnyList's undocumented API.
use anylist_rs::{AnyListClient, Ingredient, Result};
#[tokio::main]
async fn main() -> Result<()> {
// Authenticate with email and password
let client = AnyListClient::login(
"your-email@example.com",
"your-password"
).await?;
// Get all lists
let lists = client.get_lists().await?;
for list in &lists {
println!("List: {} ({} items)", list.name, list.items.len());
}
// Create a new list
let grocery_list = client.create_list("Weekly Groceries").await?;
println!("Created list: {}", grocery_list.name);
// Add items to the list
client.add_item(&grocery_list.id, "Milk").await?;
client.add_item_with_details(
&grocery_list.id,
"Apples",
Some("2 lbs"),
Some("Organic if possible"),
Some("Produce")
).await?;
Ok(())
}
Add this to your Cargo.toml:
[dependencies]
anylist_rs = "0.1.0"
tokio = { version = "1", features = ["full"] }
anylist_rsThe client automatically manages authentication tokens and refreshes them on 401 errors. You can also save and restore sessions:
use anylist_rs::{AnyListClient, SavedTokens};
// Initial login
let client = AnyListClient::login("email@example.com", "password").await?;
// Export tokens for persistence (e.g., save to keychain/config)
let tokens: SavedTokens = client.export_tokens()?;
// save_to_storage(&tokens)?;
// Later, restore from saved tokens
let tokens: SavedTokens = load_from_storage()?;
let client = AnyListClient::from_tokens(tokens)?;
// Use the client - tokens automatically refresh on 401
let lists = client.get_lists().await?;
You can optionally track authentication events:
use anylist_rs::{AnyListClient, AuthEvent};
let client = AnyListClient::login("email@example.com", "password")
.await?
.on_auth_event(|event| {
match event {
AuthEvent::TokensRefreshed => println!("Tokens refreshed!"),
AuthEvent::RefreshFailed(err) => eprintln!("Refresh failed: {}", err),
}
});
If you want manual control over token refresh:
let client = AnyListClient::login("email@example.com", "password")
.await?
.disable_auto_refresh();
// Now 401 errors will be returned instead of automatically refreshing
By default, anylist_rs uses native-tls to use the operating system's native TLS implementation.
However, if native TLS is unavailable (e.g. cros-compliation), you can use rustls instead via the rustls-tls feature.
[dependencies]
anylist_rs = { version = "0.1.0", default-features = false, features = ["rustls-tls"] }
Real-time sync via WebSockets
wss://www.anylist.com/data/add-user-listener?access_token=<JWT>Logical timestamps for conflict resolution
Photo upload/download support (S3 presigned URLs)
List folders and organization
Recipe web import from URLs
iCalendar feed export for meal planning
I made this on my own, without help or knowledge from the AnyList folks. Please, don't use this for malice.