Annotated version of this introductory video
Datasette is a tool for exploring and publishing data. It helps people take data of any shape, analyze and explore it, and publish it as an interactive website and accompanying API.
Datasette is aimed at data journalists, museum curators, archivists, local governments, scientists, researchers and anyone else who has data that they wish to share with the world. It is part of a wider ecosystem of 44 tools and 154 plugins dedicated to making working with structured data as productive as possible.
Try a demo and explore 33,000 power plants around the world, then follow the tutorial or take a look at some other examples of Datasette in action.
Then read how to get started with Datasette, subscribe to the newsletter and consider signing up for office hours for an in-person conversation about the project.
Datasette Desktop is a macOS desktop application for easily running Datasette on your own computer!
Exploratory data analysis
Import data from CSVs, JSON, database connections and more. Datasette will automatically show you patterns in your data and help you share your findings with your colleagues.
Instant data publishing
datasette publish lets you instantly publish your data to hosting providers like Google Cloud Run, Heroku or Vercel.
Rapid prototyping
Spin up a JSON API for any data in minutes. Use it to prototype and prove your ideas without building a custom backend.
Latest news and blog
13th May 2026
19th April 2026 #
Here's a new TIL on using SQL functions in Google Sheets to fetch data from Datasette.
15th April 2026 #
Datasette 1.0a27 changes how CSRF protection works in a way that simplifies form and API integration, and introduces a new RenameTableEvent for when a table is renamed by a SQL query.
18th March 2026 #
Datasette 1.0a26 adds a column_types system allowing columns to carry additional type information such as email or url, or extra types defined by plugins. This alpha also adds a UI for selecting and sorting visible columns on a table page.
25th February 2026 #
Datasette 1.0a25 adds write_wrapper() and register_token_handler() plugin hooks.
29th January 2026 #
Datasette 1.0a24 introduces a new await request.form(files=True) method for accepting file uploads, plus various other changes.
5th November 2025 #
Datasette 0.65.2 and Datasette 1.0a21 have been released with a security fix for an open redirect error, see this advisory. The latest Datasette alphas also include a breaking change to Datasette's permission system, described in detail in A new SQL-powered permissions system in Datasette 1.0a20.
6th February 2025 #
Datasette 1.0a17 is the latest Datasette 1.0 alpha release, with bug fixes and small feature improvements from the last few months.
7th October 2024 #
Python 3.13 was released today. Datasette 1.0a16 is compatible with Python 3.13, but Datasette 0.64.8 was not. The new Datasette 0.65 release fixes compatibility with the new version of Python.
5th August 2024 #
Datasette 1.0a14 includes some breaking changes to how metadata works for plugins, described in detail in the new upgrade guide. See also the annotated release notes that accompany this release.
18th February 2024 #
Datasette 1.0a10 is a focused alpha that changes some internal details about how Datasette handles transactions. The datasette.execute_write_fn() internal method now wraps the function in a database transaction unless you pass transaction=False.
16th February 2024 #
Datasette 1.0a9 adds basic alter table support to the JSON API, tweaks how permissions works and introduces some new plugin debugging utilities.
7th February 2024 #
Datasette 1.0a8 introduces several new plugin hooks, a JavaScript plugin system and moves plugin configuration from metadata.yaml to datasette.yaml. Read more about the release in the annotated release notes for 1.0a8.
1st December 2023 #
Datasette Enrichments is a new feature for Datasette that supports enriching data by running custom code against every selected row in a table. Read Datasette Enrichments: a new plugin framework for augmenting your data for more details, plus a video demo of enrichments for geocoding addresses and processing text and images using GPT-4.
30th November 2023 #
datasette-comments is a new plugin by Alex Garcia which adds collaborative commenting to Datasette. Alex built the plugin for Datasette Cloud, but it's also available as an open source package for people who are hosting their own Datasette instances. See Annotate and explore your data with datasette-comments on the Datasette Cloud blog for more details.
Latest releases
13th May 2026
datasette-comments 0.1.2.a6 - A Datasette plugin for commenting on tables, rows, and values
12th May 2026
datasette 1.0a29 - An open source multi-tool for exploring and publishing data
- New
TokenRestrictions.abbreviated(datasette)utility method for creating"_r"dictionaries. #2695 - Table headers and column options are now visible even if a table contains zero rows. #2701
- Fixed bug with display of column actions dialog on Mobile Safari. #2708
- Fixed bug where tests could crash with a segfault due to a race condition between
Datasette.close()andDatasette.close(). #2709
llm 0.32a2 - CLI utility and Python library for interacting with Large Language Models from organizations like OpenAI, Anthropic and Gemini plus local models installed on your own machine.
Support for the OpenAI Responses API
Most reasoning-capable OpenAI models now use the /v1/responses endpoint instead of /v1/chat/completions. This enables interleaved reasoning across tool calls for GPT-5 class models. #1435
- New
ResponsesandAsyncResponsesmodel classes driving the OpenAI Responses API. The existingChatandAsyncChatclasses are unchanged so other plugins that import them keep working. - The following models now use the Responses API by default:
o1,o3-mini,o3,o4-mini,gpt-5,gpt-5-mini,gpt-5-nano,gpt-5.1,gpt-5.2,gpt-5.4,gpt-5.4-mini,gpt-5.4-nano,gpt-5.5(and their pinned date variants). - Use
-o chat_completions 1to fall back to the older/v1/chat/completionscode path for any of these models. - Encrypted reasoning items are captured as
provider_metadataonReasoningPartobjects and round-tripped back to OpenAI on subsequent turns. - Reasoning summaries are now requested with
"summary": "auto"so visible reasoning text is streamed back where the model produces it, unless--hide-reasoningorhide_reasoning=is set. - This means OpenAI prompts run using
llm promptthat return reasoning tokens will display those on standard error.
CLI
- New
llm -m model --optionsflag to list the options supported by a given model. #1441 - The
-R/--no-reasoningoption has been renamed to-R/--hide-reasoning.
Python API
- New
hide_reasoning=Truekeyword argument onmodel.prompt(),conversation.prompt(),model.chain(),conversation.chain(), and their async counterparts, exposed to model plugins asprompt.hide_reasoning. Model plugins can use this to decide if they should request visible reasoning summaries from their providers. #1442 - New
options=dict keyword argument onModel.prompt(),Conversation.prompt(),Response.reply(), and their async equivalents, matching the pattern already used by.chain(). The previous**kwargsform continues to work for backwards compatibility but is no longer documented, and will be removed in the future. #1432
Bug fixes
add_tool_call()calls that were not also recorded as stream events are now correctly emitted asToolCallPartobjects when assembling response parts, so they survive serialization viaresponse.to_dict(). #1433
29th April 2026
llm 0.32a1
- Fixed a bug in 0.32a0 where tool-calling conversations were not correctly reinflated from SQLite. #1426
llm 0.32a0
This alpha introduces a major backwards-compatible refactor. Models can now be prompted with a list of messages, OpenAI Chat Completions style, and the response can now be iterated over as a sequence of mixed types of content, for example reasoning tokens mixed with text tokens mixed with tool calls.
For more background on this release take a look at the annotated release notes on my blog.
Prompt inputs and response outputs are now expressed as a list of Message objects, each containing typed Part objects (text, reasoning, tool calls, tool results, attachments).
The llm CLI tool can now display reasoning tokens while executing a prompt.
Plugin authors should read the expanded Advanced model plugins documentation, which now covers StreamEvent, consuming prompt.messages, and round-tripping opaque provider metadata such as Anthropic extended-thinking signatures and Gemini thoughtSignature values.
Structured messages and streaming events
- New
llm.Messagevalue type and constructor helpersllm.user(),llm.assistant(),llm.system(), andllm.tool_message()for building structured prompt inputs. The helpers accept strings,Attachmentinstances, or nestedPartlists. - New
messages=keyword argument onmodel.prompt(),conversation.prompt(),model.chain(),conversation.chain(), and their async counterparts. Theprompt=,system=,attachments=, andtool_results=keywords still work and synthesize into the sameMessagelist internally. - New
response.stream_events()andresponse.astream_events()methods yielding typedStreamEventobjects (typeis one of"text","reasoning","tool_call_name","tool_call_args","tool_result", plus aredacted=Truemarker for opaque reasoning). Iterating againstresponsedirectly continues to yield only text strings. - New
response.messages()method (async:await response.messages()) returning the assembledlist[Message]produced by the model. Calling it forces execution if the response prompt has not yet been executed. - New
response.reply(prompt=None, **kwargs)method that continues the conversation from anyResponse, regardless of origin. When the previous response made tool calls andtool_results=was not passed,reply()automatically executes the pending tool calls and threads the results into the next turn. On async responsesreply()is awaitable. - New
response.to_dict()andResponse.from_dict(data, *, model=None)for JSON-safe serialization of a full conversation turn --- model id, input chain, assembled output (including reasoning parts and provider metadata), options, and audit fields. Reasoning signatures andthoughtSignaturevalues round-trip viaprovider_metadata, so multi-turn extended thinking works across process boundaries. - New
llm/serialization.pymodule exposingMessageDict,PartDict,ResponseDict,PromptDict,UsageDict,AttachmentDict, and the per-Part TypedDicts. Everyto_dict()/from_dict()method is annotated with the matching TypedDict. Response.prompt.messagesis now the canonical structured input across the entire conversation chain.Conversation.promptandAsyncConversation.promptpre-compute the full chain (prior input + prior output + new turn) before constructing the nextPrompt, soresponse.prompt.messagesis always exactly what the model was sent.
CLI
llm promptandllm chatnow display visible reasoning text to stderr in a dim style while the response streams.- New
-R/--no-reasoningflag forllm promptandllm chatto suppress the reasoning stream. llm logsnow renders any visible reasoning emitted during a response under a## Reasoningheading above the response.- New
reasoningcolumn on theresponsestable populated from the visible-reasoning text.
24th April 2026
llm 0.31
- New GPT-5.5 OpenAI model:
llm -m gpt-5.5. #1418 - New option to set the text verbosity level for GPT-5+ OpenAI models:
-o verbosity low. Values arelow,medium,high. - New option for setting the image detail level used for image attachments to OpenAI models:
-o image_detail low- values arelow,highandauto, and GPT-5.4 and 5.5 also acceptoriginal. - Models listed in
extra-openai-models.yamlare now also registered as asynchronous. #1395
17th April 2026
datasette-public 0.4a1 - Make specific Datasette tables visible to the public
- Upgraded for compatibility with Datasette 1.0a28.
- Fixed
'duplicate column name: query_name'warning on startup.
datasette 1.0a28 - An open source multi-tool for exploring and publishing data
- Fixed a compatibility bug introduced in 1.0a27 where
execute_write_fn()callbacks with a parameter name other thanconnwere seeing errors. (#2691) - The database.close() method now also shuts down the write connection for that database.
- New datasette.close() method for closing down all databases and resources associated with a Datasette instance. This is called automatically when the server shuts down. (#2693)
- Datasette now includes a pytest plugin which automatically calls
datasette.close()on temporary instances created in function-scoped fixtures and during tests. See Automatic cleanup of Datasette instances for details. This helps avoid running out of file descriptors in plugin test suites that were written before theDatabase(is_temp_disk=True)feature introduced in Datasette 1.0a27. (#2692)
datasette-comments 0.1.2.a4 - A Datasette plugin for commenting on tables, rows, and values
datasette-comments 0.1.2.a3
datasette-comments 0.1.2.a2
datasette-comments 0.1.2.a1
15th April 2026
datasette-export-database 0.3a1
- Upgraded for compatibility with Datasette 1.0a27.
datasette 1.0a27 - An open source multi-tool for exploring and publishing data
CSRF protection no longer uses CSRF tokens
Datasette's token-based CSRF protection has been replaced with a mechanism based on the Sec-Fetch-Site and Origin request headers, which are supported by all modern browsers. See this article by Filippo Valsorda for more details of this approach. This removes the need for CSRF tokens in forms and AJAX requests. (#2689)
RenameTableEvent when a table is renamed
Renaming a table within Datasette will now fire a new RenameTableEvent, which plugins can use to react by updating ACL records or re-assigning comments or other associated records to the new table name. (#2681)
This event will not be fired if the table is renamed by SQL running in some other process.
The datasette.track_event() method can now be called from within a write operation (using database.execute_write() and related methods) and the event will be fired after the write transaction has successfully committed. (#2682)
Other changes
- New actor= parameter for
datasette.clientmethods, allowing internal requests to be made as a specific actor. This is particularly useful for writing automated tests. (#2688) - New
Database(is_temp_disk=True)option, used internally for the internal database. This helps resolve intermittent database locked errors caused by the internal database being in-memory as opposed to on-disk. (#2683) (#2684) - The
/<database>/<table>/-/upsertAPI (docs) now rejects rows withnullprimary key values. (#1936) - Improved example in the API explorer for the
/-/upsertendpoint (docs). (#1936) - The
/<database>.jsonendpoint now includes an"ok": truekey, for consistency with other JSON API responses. - call_with_supported_arguments() is now documented as a supported public API. (#2678
9th April 2026
datasette-gzip 0.3 - Add gzip compression to Datasette
- Depend on asgi-gzip >= 0.3 to avoid compressing
text/event-stream.