An excerpt from the repository, fetched Nov 13, 2026.
Read the project’s introduction
restclient.el
This is a tool to manually explore and test HTTP REST webservices.
Runs queries from a plain-text query sheet,
displays results as a pretty-printed XML, JSON and even images.
Usage
You can easily install restclient using package.el from MELPA.
Alternatively, deploy restclient.el into your site-lisp as usual,
then add (require 'restclient) to your Emacs start-up file.
Once installed, you can prepare a text file with queries.
restclient-mode is a major mode which does a bit of highlighting
and supports a few additional keypresses:
C-c C-c: runs the query under the cursor, tries to pretty-print the response (if possible)
C-c C-r: same, but doesn't do anything with the response, just shows the buffer
C-c C-v: same as C-c C-c, but doesn't switch focus to other window
C-c C-b: same as C-c C-c, but doesn't show response buffer
C-c C-p: jump to the previous query
C-c C-n: jump to the next query
C-c C-.: mark the query under the cursor
C-c C-u: copy query under the cursor as a curl command
C-c C-g: start a helm session with sources for variables and requests (if helm is available, of course)
C-c n n: narrow to region of current request (including headers)
TAB: hide/show current request body, only if
C-c C-a: show all collapsed regions
C-c C-i: show information on restclient variables at point
The last two functions are implemented as restclient-outline-mode minor mode, which is activated by default via hook for major mode. Remove this hook using (remove-hook 'restclient-mode-hook 'restclient-outline-mode) if you don't wish to have this behaviour, or it clashes with any other binding for TAB like autocomplete.
Query file example:
# -*- restclient -*-
#
# Gets all Github APIs, formats JSON, shows response status and headers underneath.
# Also sends a User-Agent header, because the Github API requires this.
#
GET https://api.github.com
User-Agent: Emacs Restclient
#
# XML is supported - highlight, pretty-print
#
GET http://www.redmine.org/issues.xml?limit=10
#
# It can even show an image!
#
GET http://upload.wikimedia.org/wikipedia/commons/6/63/Wikipedia-logo.png
#
# A bit of json GET, you can pass headers too
#
GET http://jira.atlassian.com/rest/api/latest/issue/JRA-9
User-Agent: Emacs24
Accept-Encoding: compress, gzip
#
# Post works too, entity just goes after an empty line. Same is for PUT.
#
POST https://jira.atlassian.com/rest/api/2/search
Content-Type: application/json
{
"jql": "project = HCPUB",
"startAt": 0,
"maxResults": 15,
"fields": [
"summary",
"status",
"assignee"
]
}
#
# And delete, will return not-found error...
#
DELETE https://jira.atlassian.com/rest/api/2/version/20
# Set a variable to the value of your ip address using a jq expression
GET http://httpbin.org/ip
-> jq-set-var :my-ip .origin
Lines starting with # are considered comments AND also act as separators.
HTTPS and image display requires additional dll's on windows (libtls, libpng, libjpeg etc), which are not in the emacs distribution.
More examples can be found in the examples directory.
In-buffer variables
You declare a variable like this:
:myvar = the value
or like this:
:myvar := (some (artbitrary 'elisp)
In second form, the value of variable is evaluated as Emacs Lisp form immediately. Evaluation of variables is done from top to bottom. Only one one-line form for each variable is allowed, so use (progn ...) and some virtual line wrap mode if you need more. There's no way to reference earlier declared restclient variables, but you can always use setq to save state.
Variables can be multiline too:
:myvar = <<
Authorization: :my-auth
Content-Type: application/json
User-Agent: SomeApp/1.0
#
or
:myvar := <<
(some-long-elisp
(code spanning many lines)
#
<< is used to mark a start of multiline value, the actual value is starting on the next line then. The end of such variable value is the same comment marker # and last end of line doesn't count, same is for request bodies.
After the var is declared, you can use it in the URL, the header values
and the body.
# Some generic vars
:my-auth = 319854857345898457457
:my-headers = <<
Authorization: :my-auth
Content-Type: application/json
User-Agent: SomeApp/1.0
#
# Update a user's name
:user-id = 7
:the-name := (format "%s %s %d" 'Neo (md5 "The Chosen") (+ 100 1))
PUT http://localhost:4000/users/:user-id/
:my-headers
{ "name": ":the-name" }
Varaibles can also be set based on the body of a response using the per-request hooks
# set a variable :my-ip to the value of your ip address using elisp evaluated in the result buffer
GET http://httpbin.org/ip
-> run-hook (restclient-set-var ":my-ip" (cdr (assq 'origin (json-read))))
# same thing with jq if it's installed
GET http://httpbin.org/ip
-> jq-set-var :my-ip .origin
# set a variable :my-var using a more complex jq expression (requires jq-mode)
GET https://httpbin.org/json
-> jq-set-var :my-var .slideshow.slides[0].title
# hooks come before the body on POST
POST http://httpbin.org/post
-> jq-set-var :test .json.test
{"test": "foo"}
File uploads
Restclient now allows to specify file path to use as a body, like this:
POST http://httpbin.org/post
Content-type: text/plain
< /etc/passwd
Caveats:
Multiline variables can be used in headers or body. In URL too, but it doesn't make sense unless it was long elisp expression evaluating to simple value.
Yet same variable cannot contain both headers and body, it must be split into two and separated by empty line as usual.
Variables now can reference each other, substitution happens in several passes and stops when there's no more variables. Please avoid circular references. There's customizable safeguard of maximum 10 passes to prevent hanging in this case, but it will slow things down.
Variable declaration only considered above request line.
Be careful of what you put in that elisp. No security checks are done, so it can format your hardrive. If there's a parsing or e
Read the full README on GitHub