Unofficial Node.js wrapper for the API of the Picnic online supermarket. Not affiliated with Picnic.
npm install picnic-apiImport the package and create a client. All configuration options are optional.
import PicnicClient from "picnic-api";
const picnicClient = new PicnicClient({
countryCode: "NL", // The country code for the API. Options: "NL" (default), "DE" or "FR".
authKey: "...", // An existing auth key to skip the login step.
apiVersion: "15", // The API version (defaults to "15").
url: "...", // A custom base URL (defaults to https://storefront-prod.<countryCode>.picnicinternational.com/api/<apiVersion>).
deviceId: "...", // Custom device identifier for x-picnic-did header. (defaults to "3C417201548B2E3B")
agent: "...", // Custom agent string for x-picnic-agent header. (defaults to "30100;1.228.1-15480;")
});Most endpoints require authentication. Call auth.login() to obtain an auth key, which is automatically stored in the client and sent with subsequent requests. If you already have a key from a previous session, pass it as authKey in the constructor instead.
If the login endpoint responds with a 2FA requirement (second_factor_authentication_required: true), then call auth.generate2FACode("SMS") to generate a 2FA code and pass it to auth.verify2FA(<code>) to complete the login process.
await picnicClient.auth.login("email", "password");
// If 2FA is required:
await picnicClient.auth.generate2FACode("SMS");
await picnicClient.auth.verify2FA("123456");// Search for products
const results = await picnicClient.catalog.search("Affligem blond");
// Add a product to the cart
await picnicClient.cart.addProductToCart(11295810, 2);
// Bulk add products to the cart
await picnicClient.cart.addProductsToCart([
{ productId: "s11295810", quantity: 2 },
{ productId: "s10000123", quantity: 1 },
]);
// Get available delivery slots
const slots = await picnicClient.cart.getDeliverySlots();
// Get details of a specific delivery
const delivery = await picnicClient.delivery.getDelivery("delivery-id");For endpoints not yet covered by a domain service, use sendRequest directly:
await picnicClient.sendRequest("GET", "/unknown/route");
await picnicClient.sendRequest("POST", "/invite/friend", { email: "friend@example.com" });The client exposes the following domain services, each grouping a set of related endpoints:
| Service | Accessor | Description |
|---|---|---|
| App | client.app |
Bootstrap data, pages, and deeplink resolution. |
| Auth | client.auth |
Login, logout, 2FA, and phone verification. |
| Cart | client.cart |
Cart management, delivery slots and selling units (recipes, meal plans, selling groups). |
| Catalog | client.catalog |
Product search, suggestions, details, and images. |
| Consent | client.consent |
Consent settings and GDPR declarations. |
| Content | client.content |
Static content pages (FAQ, search empty state). |
| Customer Service | client.customerService |
Contact info, messages, reminders, and parcels. |
| Delivery | client.delivery |
Delivery history, live position, ratings, and invoices. |
| Payment | client.payment |
Payment profile and wallet transactions. |
| Recipe | client.recipe |
Recipe browsing and saving. |
| User | client.user |
User details, profile, suggestions, and push tokens. |
| User Onboarding | client.userOnboarding |
Household/business details and push subscriptions. |
Each service method is fully typed — explore the type definitions under src/domains/<service>/types.ts for request and response shapes.
Contributions are welcome! Please read the CONTRIBUTING.md file for guidelines.
If you enjoy this package, consider using the discount code MAAR3267 so we both get a discount on our next order. 😄