A Python API v2 wrapper for Tumblr providing comprehensive methods for user, blog, and post operations with OAuth authentication
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Complete post lifecycle management including creation of all Tumblr post types (text, photo, quote, link, chat, audio, video), editing, reblogging, deletion, and notes retrieval. These methods require authentication and appropriate permissions for the target blog.
Create posts of all Tumblr post types with comprehensive parameter support and file upload capabilities.
Create text-based content with markdown or HTML formatting support.
def create_text(self, blogname: str, **kwargs) -> dict:
"""
Create a text post.
Args:
blogname (str): Blog URL to post to (e.g., 'my-blog.tumblr.com')
Parameters:
title (str, optional): Post title (supports HTML/markdown)
body (str, optional): Post body content (supports HTML/markdown)
state (str, optional): Post state ('published', 'draft', 'queue', 'private')
tags (list, optional): List of tag strings
tweet (str, optional): Custom tweet text
date (str, optional): GMT date and time for the post
format (str, optional): Content format ('html' or 'markdown')
slug (str, optional): URL slug for the post
Returns:
dict: Created post information including ID
"""Usage example:
# Create a simple text post
client.create_text(
'my-blog.tumblr.com',
title='Hello World',
body='This is my first post using **PyTumblr**!',
state='published',
tags=['python', 'tumblr', 'first-post'],
format='markdown'
)Create photo posts and photosets with local file upload or external URL support.
def create_photo(self, blogname: str, **kwargs) -> dict:
"""
Create a photo post or photoset.
Args:
blogname (str): Blog URL to post to (e.g., 'my-blog.tumblr.com')
Parameters:
caption (str, optional): Photo caption (supports HTML/markdown)
link (str, optional): Click-through URL for the photo
source (str, optional): External photo URL (use this OR data, not both)
data (str or list, optional): Local file path(s) for upload
photoset_layout (str, optional): Layout for photoset
state (str, optional): Post state ('published', 'draft', 'queue', 'private')
tags (list, optional): List of tag strings
tweet (str, optional): Custom tweet text
date (str, optional): GMT date and time for the post
format (str, optional): Content format ('html' or 'markdown')
slug (str, optional): URL slug for the post
Returns:
dict: Created post information including ID
"""Usage examples:
# Create photo post from URL
client.create_photo(
'my-blog.tumblr.com',
source='https://example.com/image.jpg',
caption='Beautiful sunset!',
tags=['photography', 'sunset']
)
# Upload local photo
client.create_photo(
'my-blog.tumblr.com',
data='/path/to/photo.jpg',
caption='My latest artwork',
state='queue'
)
# Create photoset from multiple files
client.create_photo(
'my-blog.tumblr.com',
data=['/path/to/photo1.jpg', '/path/to/photo2.jpg'],
caption='Photo collection from my trip',
photoset_layout='1,1'
)Create inspirational or quoted content with source attribution.
def create_quote(self, blogname: str, **kwargs) -> dict:
"""
Create a quote post.
Args:
blogname (str): Blog URL to post to (e.g., 'my-blog.tumblr.com')
Parameters:
quote (str, optional): The full text of the quote
source (str, optional): Source/attribution for the quote (supports HTML)
state (str, optional): Post state ('published', 'draft', 'queue', 'private')
tags (list, optional): List of tag strings
tweet (str, optional): Custom tweet text
date (str, optional): GMT date and time for the post
format (str, optional): Content format ('html' or 'markdown')
slug (str, optional): URL slug for the post
Returns:
dict: Created post information including ID
"""Usage example:
client.create_quote(
'my-blog.tumblr.com',
quote='The only way to do great work is to love what you do.',
source='Steve Jobs',
tags=['inspiration', 'quotes']
)Share external links with descriptions and thumbnails.
def create_link(self, blogname: str, **kwargs) -> dict:
"""
Create a link post.
Args:
blogname (str): Blog URL to post to (e.g., 'my-blog.tumblr.com')
Parameters:
title (str, optional): Link title (supports HTML entities)
url (str, optional): The URL to link to
description (str, optional): Description of the linked content
thumbnail (str, optional): Thumbnail image URL
state (str, optional): Post state ('published', 'draft', 'queue', 'private')
tags (list, optional): List of tag strings
tweet (str, optional): Custom tweet text
date (str, optional): GMT date and time for the post
format (str, optional): Content format ('html' or 'markdown')
slug (str, optional): URL slug for the post
Returns:
dict: Created post information including ID
"""Usage example:
client.create_link(
'my-blog.tumblr.com',
title='Amazing Search Engine',
url='https://duckduckgo.com',
description='Privacy-focused search that doesn\'t track you.',
tags=['privacy', 'search', 'tools']
)Create conversation or dialogue posts with formatted exchanges.
def create_chat(self, blogname: str, **kwargs) -> dict:
"""
Create a chat post.
Args:
blogname (str): Blog URL to post to (e.g., 'my-blog.tumblr.com')
Parameters:
title (str, optional): Chat title
conversation (str, optional): The conversation text (no HTML, dialogue labels)
state (str, optional): Post state ('published', 'draft', 'queue', 'private')
tags (list, optional): List of tag strings
tweet (str, optional): Custom tweet text
date (str, optional): GMT date and time for the post
format (str, optional): Content format ('html' or 'markdown')
slug (str, optional): URL slug for the post
Returns:
dict: Created post information including ID
"""Usage example:
chat_text = """Alice: Did you see the latest Python release?
Bob: Yes! The new features are amazing.
Alice: I especially love the pattern matching.
Bob: Same here, makes code so much cleaner."""
client.create_chat(
'my-blog.tumblr.com',
title='Python Discussion',
conversation=chat_text,
tags=['python', 'programming', 'chat']
)Share audio content from external sources or file uploads.
def create_audio(self, blogname: str, **kwargs) -> dict:
"""
Create an audio post.
Args:
blogname (str): Blog URL to post to (e.g., 'my-blog.tumblr.com')
Parameters:
caption (str, optional): Audio caption
external_url (str, optional): External audio URL (use this OR data, not both)
data (str, optional): Local audio file path for upload
state (str, optional): Post state ('published', 'draft', 'queue', 'private')
tags (list, optional): List of tag strings
tweet (str, optional): Custom tweet text
date (str, optional): GMT date and time for the post
format (str, optional): Content format ('html' or 'markdown')
slug (str, optional): URL slug for the post
Returns:
dict: Created post information including ID
"""Usage examples:
# Share external audio (SoundCloud, etc.)
client.create_audio(
'my-blog.tumblr.com',
external_url='https://soundcloud.com/artist/track',
caption='Check out this amazing track!'
)
# Upload local audio file
client.create_audio(
'my-blog.tumblr.com',
data='/path/to/song.mp3',
caption='My latest composition',
tags=['music', 'original']
)Share video content via embeds or file uploads.
def create_video(self, blogname: str, **kwargs) -> dict:
"""
Create a video post.
Args:
blogname (str): Blog URL to post to (e.g., 'my-blog.tumblr.com')
Parameters:
caption (str, optional): Video caption
embed (str, optional): HTML embed code for the video (use this OR data, not both)
data (str, optional): Local video file path for upload
state (str, optional): Post state ('published', 'draft', 'queue', 'private')
tags (list, optional): List of tag strings
tweet (str, optional): Custom tweet text
date (str, optional): GMT date and time for the post
format (str, optional): Content format ('html' or 'markdown')
slug (str, optional): URL slug for the post
Returns:
dict: Created post information including ID
"""Usage examples:
# Embed YouTube video
client.create_video(
'my-blog.tumblr.com',
embed='https://www.youtube.com/watch?v=dQw4w9WgXcQ',
caption='Classic video that never gets old'
)
# Upload local video
client.create_video(
'my-blog.tumblr.com',
data='/path/to/video.mp4',
caption='Behind the scenes footage',
tags=['video', 'bts']
)Edit existing posts, reblog content, and delete posts.
def edit_post(self, blogname: str, **kwargs) -> dict:
"""
Edit an existing post.
Args:
blogname (str): Blog URL containing the post
Parameters:
id (int, required): Post ID to edit
type (str, optional): Post type (helps with validation)
[All post-type-specific parameters available based on type]
Returns:
dict: Updated post information
"""
def reblog(self, blogname: str, **kwargs) -> dict:
"""
Reblog a post.
Args:
blogname (str): Blog URL to reblog to
Parameters:
id (int, required): Post ID to reblog
reblog_key (str, required): Reblog key from original post
comment (str, optional): Comment to add to the reblog
[All common post parameters available]
Returns:
dict: Reblogged post information
"""
def delete_post(self, blogname: str, id: int) -> dict:
"""
Delete a post.
Args:
blogname (str): Blog URL containing the post
id (int): Post ID to delete
Returns:
dict: Deletion confirmation
"""Usage examples:
# Edit a text post
client.edit_post(
'my-blog.tumblr.com',
id=123456789,
type='text',
title='Updated Title',
body='Updated content'
)
# Reblog with comment
client.reblog(
'my-blog.tumblr.com',
id=987654321,
reblog_key='abc123def',
comment='Great post! Thanks for sharing.',
tags=['reblog', 'interesting']
)
# Delete a post
client.delete_post('my-blog.tumblr.com', 123456789)Retrieve notes (likes, reblogs, replies) for posts.
def notes(self, blogname: str, id: str, **kwargs) -> dict:
"""
Get notes for a specific post.
Args:
blogname (str): Blog URL containing the post
id (str): Post ID
Parameters:
mode (str, optional): Undocumented parameter
before_timestamp (str, optional): Get notes before this timestamp
Returns:
dict: Post notes and pagination info
"""Usage example:
# Get notes for a post
notes = client.notes('example-blog.tumblr.com', '123456789')
# Paginate through notes
if notes.get('_links', {}).get('next'):
next_params = notes['_links']['next']['query_params']
more_notes = client.notes(
'example-blog.tumblr.com',
'123456789',
before_timestamp=next_params['before_timestamp']
)Find posts across Tumblr by tags.
def tagged(self, tag: str, **kwargs) -> dict:
"""
Get posts with a specific tag from across Tumblr.
Args:
tag (str): Tag to search for
Parameters:
before (int, optional): Unix timestamp to get posts before
limit (int, optional): Number of posts to return (default: 20, max: 20)
filter (str, optional): Post format ('html', 'text', 'raw')
api_key (str, optional): For public access without authentication
Returns:
dict: Tagged posts from across Tumblr
"""Usage example:
# Find posts tagged with specific term
tagged_posts = client.tagged('photography', limit=20)
# Get older posts with pagination
older_posts = client.tagged('art', before=1234567890)All post creation methods support these common parameters:
common_params = {
'state': 'published', # 'published', 'draft', 'queue', 'private'
'tags': ['tag1', 'tag2'], # List of strings
'tweet': 'Custom tweet text [URL]', # Custom tweet
'date': '2023-12-01 12:00:00 GMT', # GMT date/time
'format': 'html', # 'html' or 'markdown'
'slug': 'custom-url-slug' # URL slug
}Post management methods return detailed error information:
response = client.create_text('my-blog', title='Test', body='Content')
if response.get('meta', {}).get('status') != 201: # 201 = Created
print(f"Error: {response.get('meta', {}).get('msg')}")
if 'errors' in response.get('response', {}):
for error in response['response']['errors']:
print(f"Field error: {error}")Common error scenarios:
Install with Tessl CLI
npx tessl i tessl/pypi-pytumblr