A quick script to pull links from Tumblr
I use Tumblr as a linkblog: kittell.tumblr.com. Read an article or listen to a radio show (a "Pod Cast"), then throw the link to it up there—for what reason, I'm not sure. Probably just note hoarding. What if the though slips away, etc.
Anyway, they're there, and I'll scroll back through the list and grab a few article/show links for the newsletter. I've always wanted to make something that will go back and manage the links for me, plus the notes that about the article that I keep in Instapaper or OneNote (or Evernote, that's how long I've been thinking about it, I haven't used that service in years, thanks private equity). There's no need for that either, just a fun project to see how things work.
So here's a quick something (tumblr_2026-01-29.py) that goes to Tumblr, finds links I've posted along with the post ID and timestamp, and brings them back. It doesn't do anything interesting with them. Step one is just getting them. It was all fairly straightforward if you look at the response except for the Neue Post Format info in the body, which is more JSON info packed into a string.
import requests
import json
import html
from pathlib import Path
from bs4 import BeautifulSoup
BLOG_IDENTIFIER = "kittell.tumblr.com"
LIMIT = 10
def load_tumblr_keys():
# Retrieve API keys from a separate location from code
# Cross-platform home directory
home = Path.home()
# Shared subpath on both Mac and PC
keyfile = home / "OneDrive" / "Programs" / "tumblr" / "tumblr_api_keys.json"
with open(keyfile, "r") as f:
return json.load(f)
def get_posts(keys):
url = f"https://api.tumblr.com/v2/blog/{BLOG_IDENTIFIER}/posts/link"
params = {
"api_key": keys['consumer_key'],
"limit": LIMIT
}
response = requests.get(url, params=params)
data = response.json()
posts = data["response"]["posts"]
return posts
def get_npfdata_from_body(body):
soup = BeautifulSoup(body, 'html.parser')
# Step 1: extract the attribute
raw = soup.p["data-npf"]
# Step 2: unescape HTML entities (" → ")
unescaped = html.unescape(raw)
# Step 3: parse JSON
npf_data = json.loads(unescaped)
return npf_data
if __name__ == "__main__":
keys = load_tumblr_keys()
posts = get_posts(keys)
for post in posts:
npf_data = get_npfdata_from_body(post['body'])
print(f'{post['id']}, {post['date']}, {npf_data['url']}')
From that, I get:
806946606212644864, 2026-01-28 01:37:33 GMT, https://www.stlpr.org/economy-business/2026-01-26/facing-insurmountable-challenges-alton-steel-will-close-doors
806809748378943488, 2026-01-26 13:22:15 GMT, https://sixsongs.blogspot.com/2008/12/winter-wonderland-snowin-on-raton.html
806809201947115520, 2026-01-26 13:13:34 GMT, https://www.npr.org/2012/01/02/144587802/winter-songs-van-zandts-snowin-on-raton
806735156158316544, 2026-01-25 17:36:38 GMT, https://www.nytimes.com/interactive/2026/01/23/weather/winter-storm-snow-maps.html
806581104350986240, 2026-01-24 00:48:03 GMT, https://timkreider.substack.com/p/the-least-merry-prankster?utm_source=substack&utm_medium=email
806411463256309762, 2026-01-22 03:51:40 GMT, https://www.agriculture.com/precision-planting-unveils-arrowtube-to-improve-corn-emergence-uniformity-11889368
806397347786588160, 2026-01-22 00:07:19 GMT, https://www.garbageday.email/p/am-i-too-stupid-to-vibe-code
806215875766157312, 2026-01-20 00:02:54 GMT, https://github.blog/ai-and-ml/generative-ai/what-ai-is-actually-good-for-according-to-developers/
806215594342072320, 2026-01-19 23:58:25 GMT, https://www.npr.org/2026/01/15/nx-s1-5611117/beat-anxiety-insomnia-get-back-to-sleep
806215385008537600, 2026-01-19 23:55:06 GMT, https://arstechnica.com/information-technology/2026/01/10-things-i-learned-from-burning-myself-out-with-ai-coding-agents/