UP | HOME

Support via Liberapay

org-protocol.el – Trigger actions in Emacs via a custom URL scheme

Org protocol

Org protocol (info "(org) Protocols") is a custom URL scheme (org-protocol://) used to trigger actions in Emacs. A common use case for Org protocol is data import (for example a web clipper), where an external application can send data to Emacs by making an Org protocol URL request.

The form of an Org protocol URL is

org-protocol://PROTOCOL?key1=val1&key2=val2…

where keyN=valN is a (key, value) pair specific to the PROTOCOL used. The value must be percent encoded.

There are three predefined protocols provided by Org protocol:

store-link
Store a link, push URL to kill-ring.
capture
Capture a note and let the user view it in a buffer before storing it.
open-source
Open local source files of published contents for editing.

Motivated users can define their own custom protocol (Note: this links to a document last updated in 2021 that is likely outdated.) using the variable org-protocol-protocol-alist.

The diagram below illustrates how an Org Protocol request is handled.

org-protocol-architecture.svg

The scheme handler for GNU/Linux and Windows is typically emacsclient. On recent versions of macOS (since Ventura), security policy prevents external applications from calling programs like emacsclient outside of their sandbox. An alternate, commercial offering (Scrim) is available to serve as a macOS-trusted scheme handler for Org Protocol requests1. Users running a version of macOS older than Ventura can still use emacsclient as a scheme handler for Org Protocol.

Version Compliance

Guidance on this page is up to date with GNU Emacs 30.1 and Org 9.7.11. Sections where there is uncertainty on this are marked as such.

Installation and Configuration

Take the following steps to get Org protocol working for you.

  1. Setup Emacs server.
  2. Setup the Org protocol scheme handler.
  3. Test your Org protocol setup.
  4. Setup Org protocol capture.
  5. Construct an Org protocol URL request.

Steps 1, 2, and 5 are platform-specific so this section is largely organized by platform. Setting up Org protocol capture is placed in a common section as it considered platform independent.

GNU/Linux, BSD, and Unix variants

Setup Emacs server

Add the following lines to the Emacs initialization file (init.el, $HOME/.emacs) to start Emacs server.

(server-start)
(require 'org-protocol)

Either evaluate the above or restart Emacs to start the server.

Setup the Org protocol scheme handler

On GNU/Linux, Emacs 29.2+ configures emacsclient.desktop to handle Org Protocol URL requests. If your GUI window environment can use this file, no further setup is required. (NOTE: This is not true for some distributions of xdg-tools as reported in the bug #74467 - 31.0.50; org-protocol emacsclient.desktop change is not fully functional - GNU bug report logs.)

  • If you use Emacs < 30

    Most common desktop environments (Gnome, KDE et al) comply with the XDG Desktop Entry Specification. This means setting up emacsclient as the org-protocol handler using a .desktop file can be regarded as a standard way to set this up in most common desktop environments.

    Some environments, e.g. Gnome as of Gnome 3, have deprecated other configuration methods, e.g. gconftool-2 to set-up protocol handling.

    Create an org-protocol.desktop file either in ~/.local/share/applications/ to set-up emacsclient as the org-protocol handler for the current user or in /usr/share/applications to set-up a system-wide configuration:

    [Desktop Entry]
    Name=org-protocol
    Comment=Intercept calls from emacsclient to trigger custom actions
    Categories=Other;
    Keywords=org-protocol;
    Icon=emacs
    Type=Application
    Exec=emacsclient -- %u
    Terminal=false
    StartupWMClass=Emacs
    MimeType=x-scheme-handler/org-protocol;
    

    Update the cache database of MIME types handled by desktop files via:

    update-desktop-database ~/.local/share/applications/
    

Test your Org protocol setup

To test that Org protocol is setup and running, click on the JavaScript link below to store an Org link to this page.

In an Org buffer, use the binding C-c M-l (org-insert-last-stored-link) to paste the recently stored Org link.

Setup Org protocol capture

See Setup Org protocol capture in the common section.

Construct Org protocol URL Request

See Construct Org protocol URL request in the common section.


macOS

Setup Emacs Server

Recent versions of macOS (since Ventura) disallow the use of a local domain socket for inter-process communication between apps with separate sandboxes. Users using Scrim can instead setup a TCP socket 1. Add the following lines to the Emacs initialization file (init.el, $HOME/.emacs) to start Emacs server.

(setopt server-use-tcp t)
(server-start)
(require 'org-protocol)

Setup the Org protocol scheme handler

If Scrim is installed, no further setup is required as Scrim will automatically handle Org protocol URL requests 1.

Users of the Mitsuharu Yamamoto fork of Emacs also do not need to setup an Org protocol scheme handler as this fork will natively handle Org protocol URL requests.

If you are using an old version of macOS (nee Mac OS X) older than Ventura, this guidance may still be valid. If you are using macOS Ventura or newer, none of this guidance is valid.

Follow the directions for installing EmacsClient.app from https://github.com/neil-smithline-elisp/EmacsClient.app. This should configure the org-protocol for all Mac OS X browsers.

After installing EmacsClient.app you should then verify the installation. Once verified, you can begin using org-protocol.

If that doesn't work, you might check https://github.com/xuchunyang/setup-org-protocol-on-mac for building a custom handler, combined with the per-browser config information below.

Test your Org protocol setup

To test that Org protocol is setup and running, click on the JavaScript link below to store an Org link to this page.

In an Org buffer, use the binding C-c M-l (org-insert-last-stored-link) to paste the recently stored Org link.

Setup Org protocol capture

See Setup Org protocol capture in the common section.

Construct Org protocol URL request

See Construct Org protocol URL request in the common section.


Windows

Setup Emacs Server

Native Windows has no support for a local domain socket so a TCP socket is used instead. Add the following lines to the Emacs initialization file (init.el, $HOME/.emacs) to start Emacs server.

(setopt server-use-tcp t)
(server-start)
(require 'org-protocol)

Setup the Org protocol scheme handler

This section has not been updated since Windows XP and may not be valid. Updated guidance is wanted.

Windows users may register the "org-protocol" once for all by adjusting the following to their facts, save it as *.reg file and double-click it. This worked for me on Windows-XP Professional and the emasc23 from ourcomments.org (http://ourcomments.org/cgi-bin/emacsw32-dl-latest.pl). I'm no Windows user though and enhancements are more than welcome on the org-mode mailinglist. The original file is from http://kb.mozillazine.org/Register_protocol.

REGEDIT4

[HKEY_CLASSES_ROOT\org-protocol]
@="URL:Org Protocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\org-protocol\shell]
[HKEY_CLASSES_ROOT\org-protocol\shell\open]
[HKEY_CLASSES_ROOT\org-protocol\shell\open\command]
@="\"C:\\Programme\\Emacs\\emacs\\bin\\emacsclientw.exe\" \"%1\""

Test your Org protocol setup

To test that Org protocol is setup and running, click on the JavaScript link below to store an Org link to this page.

In an Org buffer, use the binding C-c M-l (org-insert-last-stored-link) to paste the recently stored Org link.

Setup Org protocol capture

See Setup Org protocol capture in the common section.

Construct Org protocol URL request

See Construct Org protocol URL request in the common section.


Common

Setup Org protocol capture

Knowledge of Org capture (info "(org) Capture") is recommended beforehand to understand how Org protocol extends it.

Org protocol capture (info "(org) The capture protocol") extends Org capture (info "(org) Capture") to support data import from external apps into Emacs. Different data types are supported for import:

url
a URL (typically of a web page)
title
the title of the web page
body
Text (typically selected) within the web page

The form of an Org protocol URL request with the capture protocol looks like this:

org-protocol://capture?template=TEMPLATE&url=URL&title=TITLE&body=BODY

In table form the following keys for the capture protocol are described as follows:

Key Description Template Placeholder Notes
template Template key   Capture template key in org-capture-templates. If omitted, then org-protocol-default-template-key is used.
url URL %:link Typically the web page URL to capture.
title Title %:description Typically the title of the above web page, but can be arbitrary.
body Body Text %i Typically the selected text in the web page, but can be arbitrary.

The template placeholder %:annotation is expanded to be an Org link constructed from url and title.

Users can define different capture templates (info "(org) Capture templates") using the template placeholders described above. These templates are added to the customizable Org variable org-capture-templates which itself is a list of templates.

An example Org protocol capture template is shown below with key name "capture". The following Elisp shows how this template can be added to org-capture-templates.

(add-hook 'org-mode-hook
 (lambda ()
   (add-to-list 'org-capture-templates
                ;; The template follows
                '("capture"
                  "Capture (Org Protocol)"
                  entry
                  (file "notes.org")
                  (function (lambda ()
                              (string-join
                               '("* %:description"
                                 ":PROPERTIES:"
                                 ":CREATED: %U"
                                 ":END:"
                                 "%:annotation"
                                 "%i"
                                 ""
                                 "%?")
                               "\n")))
                  :prepend t
                  :empty-lines 1)
                ;; End template
                )))

Setup Org protocol open source

This section needs update for Org 9.7.11.

This one was designed to help with opening sources for editing when browsing in the first place. org-protocol-open-source uses the custom variable org-protocol-project-alist to map URLs to (local) filenames.

Let's take https://orgmode.org/worg/ as our example.

Our intention is to click a bookmark (or link) to open the source of the published file we are reading in our favourite editor. The bookmark-URL above could be used again. But since org-protocol-open-source regards the first field only, this here will do:

javascript:location.href='org-protocol://open-source://'+encodeURIComponent(location.href)

To open files publihed on Worg locally, org-protocol-project-alist should look like this (you may skip the second project):

(setq org-protocol-project-alist
      '(("Worg"
         :base-url "https://orgmode.org/worg/"
         :working-directory "/home/user/worg/"
         :online-suffix ".html"
         :working-suffix ".org")
        ("My local Org-notes"
         :base-url "http://localhost/org/"
         :working-directory "/home/user/org/"
         :online-suffix ".php"
         :working-suffix ".org")))

If you're now browsing https://orgmode.org/worg/org-contrib/org-protocol.html and find a typo or have an idea how to enhance the documentation, simply click the bookmark and start editing.

There are two functions to help you fill org-protocol-project-alist with valid contents. One possibility is org-protocol-create that guides you through the process. If you're editing an Org-mode file that is part of a publishing project in org-publish-project-alist, try

M-x org-protocol-create-for-org RET
  • Handle rewritten URLs

    In some cases, replacing :base-url with :working-directory and :online-suffix with :working-suffix will not yield the desired results.

    Suppose you maintain an online store located at http://example.com/. The local sources reside in /home/user/example/. While most of the URLs map directly to local file names by stripping URL parameters from the end and replacing the :base-url with :working-diretory and :online-suffix with :working-suffix, this might not work for rewritten URLs. It's common practice to serve all products in such a store through one file and rewrite URLs that do not match an existing file on the server.

    That way, a request to http://example.com/print/posters-A4.html might be rewritten on the server to something like http://example.com/shop/products.php/posters-A4.html.php, where /posters-A4-digital.html.php is the so called path info. Note that the browser will not notice the rewrite.

    If you now click your org-protocol://open-source:// bookmark, the handler will probably not find a file named /home/user/example/print/posters-A4.html.php and fail.

    Or, even more simple, assume you're browsing http://example.com/. A file named /home/user/example/.php is not likely to exist.

    Since Org-mode commit 69b46e10aab3b2374ecbc1a963ba56e77102a9a4 from 15th Nov. 2009, such an entry in org-protocol-project-alist may hold an additional property :rewrites. This property is a list of cons cells, each of which maps a regular expression to a path relative to the :working-directory.

    Now map the URL to the path /home/user/example/products.php by adding the :rewrites property like this:

    (setq org-protocol-project-alist
          '(("example.com"
             :base-url "http://example.com/"
             :working-directory "/home/user/example/"
             :online-suffix ".php"
             :working-suffix ".php"
             :rewrites (("example.com/print/" . "products.php")
                        ("example.com/$" . "index.php"))
             )))
    

    Guess what the second :rewrites element does. Since example.com/$ is used as a regular expression, it maps http://example.com/, https://example.com, http://www.example.com/ and similar to /home/user/example/index.php.

    The :rewrites are searched as a last resort if and only if no existing file name is matched.

Construct Org protocol URL request

Numerous approaches can be used to construct an Org protocol request:

  • As a web browser bookmark that can invoke JavaScript
  • Via program/script generation (Bash, Python, Java, Go, Rust, C#, etc.)

Once the URL request has been constructed, it can be sent to Emacs via the scheme handler.

  • Web Browser Bookmark

    A cross-platform approach to constructing an Org protocol request is to create a web browser bookmark that can run JavaScript as its location.

    1. Create a bookmark in your web browser (Chrome, Firefox, Safari) named "Share Org Link".
    2. Add the following code as the location for this bookmark.

      javascript:location.href='org-protocol://store-link?' + new URLSearchParams({url:location.href, title:document.title});void(0);
      
    3. When visiting a web page, invoke the bookmark "Share Org Link" to share this link to Emacs. Note that a permission may need to be granted with this approach.

    Many different variants of this approach can be taken to cover different Org protocol request types.

  • 3rd Party Applications
    • Captee (macOS)

      Captee is an application that can construct an Org protocol URL from the macOS Share Menu1. Native apps that support the Share Menu can make an Org protocol store-link or capture request.

    • Acrobat Reader

      The guidance in this section is likely stale.

      Adapted from https://list.orgmode.org/loom.20080527T012114-502@post.gmane.org

      You place a javascript file for each menu entry in ~/.adobe/Acrobat/<VERSION>/JavaScripts on unix-like systems or c:/Program Files/Adobe/Acrobat <VERSION>/Reader/Javascripts/ on Windows, or wherever your Adobe Reader Installation might look for javascript.

      The examples given here will place new menu entries in the "Tools" menu, after restarting Adobe Reader.

      • org-store-link.js
        // from https://list.orgmode.org/loom.20080527T012114-502@post.gmane.org
        app.addMenuItem({cName:"org-store-link", cParent:"Tools",
           cExec:"app.launchURL('org-protocol://store-link://' + encodeURIComponent(this.URL) + '/' + encodeURIComponent(this.info.Title));"});
        
      • org-capture.js
        // from https://list.orgmode.org/loom.20080527T012114-502@post.gmane.org
        app.addMenuItem({cName:"org-capture", cParent:"Tools",
           cExec:"app.launchURL('org-protocol://capture://' + encodeURIComponent(this.URL) + '/' + encodeURIComponent(this.info.Title) + '/');"});
        
    • Opera

      The guidance in this section is likely stale.

      Opera setup is described here: http://www.opera.com/support/kb/view/535/.

      To set up opera for use with org-protocol, follow these steps:

      1. Choose "Tools" -> "Prefences" from the menu.
      2. Select the tab "Advanced".
      3. Choose "Programs" from the list on the left.
      4. Now click the button "Add" on the very right.
      5. In the new dialog window, enter "org-protocol" as "Protocol", choose the radio button "Open with other application" and enter the path to emacsclient.

Troubleshooting

Firefox

Firefox users can follow the steps documented on https://kb.mozillazine.org/Register_protocol.


History of Org protocol

A historical account of Org protocol is needed here.

org-protocol.el is based on code and ideas from org-annotation-helper.el and org-browser-url.el.

Deprecated URL Styles

The store-link, capture, and open-source URL styles have been changed to largely conform to the common internet scheme syntax of RFC 1738 and query component specification of RFC 3986.

This changes the format of the scheme specific part from using / to separate parameters to using HTTP query key=value style parameters.

The following tables illustrate the difference between the old and new styles. Migrating from the old style to new is recommended.

store-link  
Old Style org-protocol:/store-link:/URL/TITLE
New Style org-protocol://store-link?url=URL&title=TITLE


capture  
Old Style org-protocol:/capture:/URL/TITLE
New Style org-protocol://capture?url=URL&title=TITLE&body=BODY


open-source  
Old Style org-protocol:/open-source:/URL
New Style org-protocol://open-source?url=URL

Removed Protocols

The remember protocol is removed. Users should migrate any configuration relying on it to the capture protocol.

Screencast: small introduction to org-protocol.el

This video is obsolete. Retained for archival purposes.

This screencast shows off some nice things you can do with Firefox, Emacs, Org-mode and org-protocol.el.

It first shows how to create two bookmarklets, org-capture and org-store-link. These bookmarklets enable your Firefox to talk to emacsclient via a new protocol (org-protocol://); emacsclient then parses the request and tells Emacs to capture or store stuff at the relevant places in your Org files.

At the end of the screencast, we create two ubiquity commands from these bookmarklets. Now in Firefox ALT-SPC org-capture RET creates a note in my Org files.

Footnotes:

1

Disclaimer: author of this section, Charles Choi, is also the publisher of Scrim and Captee.

Documentation from the orgmode.org/worg/ website (either in its HTML format or in its Org format) is licensed under the GNU Free Documentation License version 1.3 or later. The code examples and css stylesheets are licensed under the GNU General Public License v3 or later.