Paprika doesn't have their API documented, so this is me reverse-engineering it from an Android device
https://knowing-grain.glitch.me/
Code: https://glitch.com/edit/#!/knowing-grain
HTTP BASIC auth (emoji shrug), and send a GET to:
- https://www.paprikaapp.com/api/v1/sync/bookmarks/
- https://www.paprikaapp.com/api/v1/sync/groceries/
- https://www.paprikaapp.com/api/v1/sync/categories/
- https://www.paprikaapp.com/api/v1/sync/recipes/
- https://www.paprikaapp.com/api/v1/sync/meals/
Syncing a particular recipe:
API uses BASIC auth; whatever your cloud sync is.
Services do not have CORS headers, so you can't invoke them directly from a browser :(
Send a POST to: https://www.paprikaapp.com/api/v1/sync/recipe/{uid-of-recipe}/
With your recipe in a multipart/form-data
, in the data
param. Example:
{
"uid": "ccb42915-5fe9-425d-98da-c1ffbe420159",
"name": "Test",
"directions": "Do",
"servings": "",
"rating": 0,
"difficulty": "Easy",
"ingredients": "Ddddjdjdd\nDjdjdjdd\nDjdhdhdhdndnee ",
"notes": "",
"created": "2018-03-26 09:00:02",
"image_url": null,
"on_favorites": 0,
"cook_time": "",
"prep_time": "",
"source": "",
"source_url": "",
"photo_hash": null,
"photo": null,
"nutritional_info": "",
"scale": null,
"deleted": false,
"categories": [
"cbaca738-cdfb-4150-960d-e1b1ac4cdcc3"
],
"hash": "162e5ad0134e9398b98057aea951304780d0396582238320c28b34a7c35f841e"
}
The data
param should be gzip-encoded
Still figuring this out 🤷♂️
Appears to be a POST
to https://www.paprikaapp.com/api/v1/sync/recipes/, no auth
Sends a multipart/form-data
with three fields:
- url:
text/plain
(e.g. https://www.kingarthurflour.com/recipes/homemade-whole-grain-pancake-mix-recipe) - styles:
file
(filenamestyles.json
) - gzippeed JSON of all the styles on the page? - html:
file
(filenamerecipe.html
) - gzipped HTML from the page
Returns a text-plain
(actually JSON) with a structure like:
{
"result": {
"cook_time": "4 mins. to 8 mins.",
"difficulty": "",
"directions": "To make the mix: Grind the oats in a food processor until they're chopped fine, but not a
powder.\n\nPut the flour, oats, and all other dry ingredients into a mixer with a paddle. Mix on slow speed, and
drizzle the vegetable oil into the bowl slowly while the mixer is running.\n\nStore in an airtight container for up
to two weeks at room temperature, or indefinitely in the refrigerator or freezer.\n\nTo make pancakes: Whisk
together 1 cup of mix, 1 cup of buttermilk (or a combination of half plain yogurt and half milk; or 3/4 cup liquid
whey), and 1 large egg. Don't worry if it seems thin at first: the oats will soak up the milk, and the mix will
thicken a bit as it stands.\n\nLet the batter stand for at least 20 minutes before cooking.\n\nHeat a lightly
greased griddle to 350°F (if you've got a griddle with a temperature setting; if not, medium-hot will do).\n\nDrop
the batter onto it in 1/4-cupfuls (a jumbo cookie scoop works well here) to make a 4\" diameter pancake. If you
have English muffin rings, use them; they make a perfectly round, evenly thick pancake.\n\nWhen the edges look dry
and bubbles come to the surface without breaking (after about 2 minutes, if your griddle is the correct
temperature), turn the pancake over to finish cooking on the second side, which will take about 2 minutes.\n\nServe
pancakes immediately, or stack and hold in a warm oven.\n\nYield: a batch using 1 cup of the mix will make about 5
to 8 pancakes, depending on size.",
"image_url": "",
"ingredients": "MIX\n4 cups King Arthur White Whole Wheat Flour or Organic White Whole Wheat Flour\n1 cup
King Arthur Unbleached All-Purpose Flour or Organic All-Purpose Flour\n3 1/2 cups old-fashioned or rolled oats\n3
tablespoons sugar\n3 tablespoons baking powder\n1 tablespoon salt\n1 tablespoon baking soda\n1 cup vegetable
oil\nPANCAKES\n1 cup homemade mix\n1 cup buttermilk, nut milk, or a combination of plain yogurt and milk; or 3/4
cup liquid whey\n1 large egg",
"name": "Homemade Whole-Grain Pancake Mix",
"notes": "",
"nutritional_info": "Calories: 110\nTotal Carbohydrates: 12g\nCholesterol: 30mg\nTotal Fat: 5g\nDietary
fiber: 3g\nProtein: 4g\nSaturated fat: 1g\nAmount Per: 1 pancake (56g)\nSodium: 260mg\nSugar: 3g\nTrans Fat: 0g",
"prep_time": "20 mins.",
"servings": "10 cups dry mix",
"total_time": ""
}
}
You can then convert it to a recipe by making a UID and POSTing it to the URLs above
@anthonydibi Well there you go, that's pretty abusive of the API and I guarantee why you're being blocked. For context the official paprika app makes 2-4 API calls when loading and browsing with less than 1mb of data and 500 recipes.
You're doing around 150x the calls on build and then ~20x every hour continuously as well as a massive amount on page load. A single person browsing your site could visit the recipes page 3-4 a visit making well over 100 calls to the API, no clue how many visitors you have.
If paprika has started doing IP bans and rate limiting it's exactly because of abuse like this.
Regenerating every hour is beyond excessive, how many recipe changes are you making?? Even one a day feels like a lot. Do some reverse engineering of how the paprika app synced, haven't looked in a while but off the top of my head they do a small call to check if there are any changes in the db and then selectively pull in those changes.
That being said if you must reload that often you really should rely on your own cached data like how the official app does