Raycast Clipboard API: Read Text Without Losing HTML
If your Raycast extension reads a rich copy as text and writes that string back, the result is a text copy. The original styling does not travel with the string.
Use Clipboard.read() when you need to inspect the available HTML as well as text. Use Clipboard.readText() when plain text is the intended input. Preserving HTML can preserve some rich content, but neither operation is a universal clone of every format on the Mac pasteboard.
Here is how to make that distinction explicit in an extension.
Choose what your command promises to preserve
“Keep the formatting” can mean several things:
| Intended result | Design choice |
|---|---|
| Process a command, identifier, or URL | Read and write plain text deliberately |
| Forward rich text when HTML is available | Read HTML and retain a text fallback |
| Preserve arbitrary app-specific clipboard data | Do not assume an HTML/text round trip can do it |
| Convert content into Markdown | Treat it as a conversion with different output |
For example, a command that normalizes a ticket number has no reason to keep a webpage's font. A command that forwards a styled support reply may have a reason to retain its links and emphasis.
Define that behavior before choosing the API. Otherwise a convenient string operation becomes an accidental format conversion.
Read the available content once
Raycast's Clipboard API reference documents read, readText, and copying HTML with an optional text representation. Read a snapshot, inspect the fields, and decide which output you can support.
This illustrative no-view command retains supplied HTML when available and falls back to supplied text. It reports a fixed error instead of logging clipboard contents:
import { Clipboard, showToast, Toast } from "@raycast/api";
export default async function Command() {
try {
const copied = await Clipboard.read();
const html = "html" in copied ? copied.html : undefined;
const text = "text" in copied ? copied.text : undefined;
if (typeof html === "string" && html.length > 0) {
await Clipboard.copy({
html,
...(typeof text === "string" ? { text } : {}),
});
} else if (typeof text === "string") {
await Clipboard.copy(text);
} else {
await showToast({
style: Toast.Style.Failure,
title: "This command supports text and HTML only",
});
return;
}
await showToast({
style: Toast.Style.Success,
title: "Supported content copied",
});
} catch {
await showToast({
style: Toast.Style.Failure,
title: "Could not copy supported content",
});
}
}
The command copies its result back to the clipboard. It does not paste into another application. That separation makes it easier to inspect the result before inserting it somewhere important. Raycast documents toast behavior separately in its feedback API.
The guards also make the unsupported case visible. This example does not claim to handle images or file copies.
Why reading text can appear to “lose” formatting
A clipboard entry can offer several representations of the same selection. A receiving application chooses a representation it understands. Apple's pasteboard documentation describes this exchange between applications.
Consider a copied link whose visible text is “Read the setup guide.” The text representation may contain those words. The HTML representation may also contain the destination URL and emphasis. Writing only the visible words cannot retain a link destination that was never included in your output.
The loss can happen at several points:
- The source supplies only plain text.
- Your command reads only text.
- Your transformation discards rich content.
- Your copy operation writes only a string.
- The destination chooses plain text or strips unsupported styling.
Check each boundary. More complicated copying code cannot invent formatting the source did not provide.
HTML is not an exact pasteboard backup
An application may use RTF, image data, multiple items, or its own private representation. Retaining HTML does not establish that those other representations survived.
Even valid HTML may render differently in two editors. A destination can reinterpret paragraph spacing, reject styles, replace fonts, or accept only text. If exact visual appearance matters, a document or image may be a better transfer format than an editable text paste.
There is also a difference between the built-in Raycast history command and an extension's public API. A history feature supporting original formats does not mean every representation is exposed through the extension method you called. Our Raycast history guide covers the user-facing workflow.
Keep recent-history access bounded
The API reference documents an offset from 0 through 5 for reading recent history. That is a bounded access mechanism, not a documented full-history search API.
Do not build a loop that assumes arbitrary offsets will enumerate everything a user has saved. If your feature needs “the last few copies,” that limit may fit. If it needs semantic search across months of clips, design for a source that explicitly supports that task.
For a different integration model, Pastea exposes approved clipboard access to compatible coding tools through MCP. Our clipboard-to-AI guide explains that workflow and its access controls. It does not extend Raycast's API or make these methods interchangeable.
Verify the destination, not just the returned fields
Before shipping a format-sensitive command, try this small matrix with harmless sample content:
| Input | What to inspect |
|---|---|
| Plain paragraph | Characters and line breaks survive |
| Bold text with a hyperlink | Emphasis and the actual link destination survive where supported |
| Table copied from a document | Cells remain useful, or the unsupported behavior is explained |
| Image or Finder file | The command reports its text/HTML limitation |
| Rich copy pasted into a plain-text editor | Text remains usable without promising styling |
These are validation cases, not measured compatibility results. Test the actual source, destination, Raycast version, and operating system you support.
An open report in Raycast's repository describes missing HTML in a Windows clipboard round trip. It is a platform-specific report, not evidence that the same bug affects Mac. It is a useful reason to verify behavior instead of treating a type signature as a compatibility test.
For ordinary Mac use, see how to paste with formatting. For extension authors, the rule is more specific: preserve the representations your command supports, describe the rest honestly, and never log a user's copied material just to find out what format it had.




