Repository navigation
Versions and Upgrading
Every published version, and what changes for a caller moving from 1.x to 2.0.0. The comparisons come from two sources. One is the repository's golden capture of 1.1.7, replayed on 2026-09-29 against 1.1.7 and 2.0.0 as installed from npm that day. The other is the same calls run side by side against the local stand-in for the API.
Dates are from the npm registry; downloads are the registry's per-version counts for the week of 2026-09-21 to 2026-09-27 (both read on 2026-09-29).
| Version | Published | Downloads that week | Status |
|---|---|---|---|
| 2.0.0 | 2026-09-26 | 182 | latest |
| 2.0.0-beta.1 | 2026-09-26 | 132 | prerelease |
| 1.1.7 | 2019-11-28 | 61 | deprecated |
| 1.1.6 | 2017-04-23 | 13 | deprecated |
| 1.1.3 to 1.1.5 | 2017-04-23 | 6 to 9 each | deprecated |
| 1.1.1 and 1.1.2 | 2016-09-18 | 6 each | deprecated |
| 1.1.0 | 2016-08-17 | 6 | deprecated |
| 1.0.0 to 1.0.2 | 2016-05-27 and 2016-05-30 | 6 each | deprecated |
Every 1.x version carries this npm deprecation message:
1.x depends on the deprecated request package, its CLI was never installable and -a was ignored; use 2.x
1.1.7 still installs (with request 2.88.2 and commander 4.1.1) and still runs on Node 20.20.2 and 24.18.0. The CHANGELOG describes 2.0.0 in full and 1.1.7 in one paragraph. The GitHub tags stop at v1.1.2 for 1.x, so 1.1.3 to 1.1.7 exist only on npm.
For a real post id, require('stack-exchange-markdown-retriever').retrieveMarkdown(options, callback) sends the same request and calls back with the same (markdown, error) in 2.0.0. What changes:
- Node 20 or later, and no deep imports (the package has an
exportsmap). - Ids that are not post ids (
'abc',-1,1.5, arrays, paths) throw aTypeErrorinstead of being sent. - Errors from the API are
StackExchangeErrorobjects with the same message, plusstatus,errorIdanderrorName. Bodies that are not JSON giveStackExchangeError: The response is not JSONwhere 1.x gave aTypeErrorabouttoString. - A callback that is not a function throws before any request; 1.x sent the request and then crashed.
- A callback that throws is called once.
- Leaving out the callback returns a Promise; 1.x sent the request and then crashed with
callback is not a function. - Requests go through
fetch, which on Node uses a proxy only when told to (Recipes); 1.x'srequestreadHTTPS_PROXYby itself. - A 30-second timeout, where 1.x waited for ever.
- The command line tool is installed,
-aworks, and errors exit 1.
This CommonJS program ran once in a project with 1.1.7 and once with 2.0.0, against the same stand-in:
const {retrieveMarkdown} = require('stack-exchange-markdown-retriever');
const calls = [
{entityId: 127968, site: 'scifi'},
{entityId: 1010, isForAnswer: true},
{entityId: 404},
{entityId: 9001},
{entityId: 9004},
{entityId: 'abc'},
];
(async () => {
for (const options of calls) {
await new Promise(resolve => {
try {
retrieveMarkdown(options, (markdown, error) => {
console.log(JSON.stringify(options.entityId), '->', JSON.stringify(markdown), error ? error.name + ': ' + error.message : null);
resolve();
});
} catch (error) {
console.log(JSON.stringify(options.entityId), '-> threw', error.name + ': ' + error.message);
resolve();
}
});
}
})();9001 is the stand-in's API error and 9004 its plain-JSON body (no compression). 1.1.7 printed (sample content):
127968 -> "Sample question body, made up for this wiki (not the real post).\n\nIt keeps HTML entities: "quoted" & more.\n\n an indented code line" null
1010 -> "Sample answer, made up for this wiki, with a [link](https://example.com/)." null
404 -> null null
9001 -> null Error: ids
9004 -> null TypeError: Cannot read properties of undefined (reading 'toString')
"abc" -> null null
2.0.0 printed (sample content):
127968 -> "Sample question body, made up for this wiki (not the real post).\n\nIt keeps HTML entities: "quoted" & more.\n\n an indented code line" null
1010 -> "Sample answer, made up for this wiki, with a [link](https://example.com/)." null
404 -> null null
9001 -> null StackExchangeError: ids
9004 -> "Sample plain JSON body." null
"abc" -> threw TypeError: entityId must be a post id (digits, or ids joined by ";"), not "abc"
1.1.7 sent abc to the API as /2.2/questions/abc; 2.0.0 sent nothing for it. The first five requests were the same on both.
1.1.7's package had no bin entry, so its cli.js ran only as node node_modules/stack-exchange-markdown-retriever/cli.js. Run that way, cli.js -a 1010 fetched question 1010 and printed null, and an API error also printed null with exit 0. 2.0.0:
exit 0
--- stdout
Sample answer, made up for this wiki, with a [link](https://example.com/).
for -a 1010 (sample content), and for the API error:
exit 1
--- stdout
--- stderr (first line)
StackExchangeError: ids
1.1.7's cli.js also refused --version (error: unknown option '--version').
The repository keeps test/golden/capture-1.1.7.cjs and its recording test/golden/1.1.7.json: 90 calls and 20 command line runs of the published 1.1.7, recorded on 2026-09-26 through the capture's own proxy with TLS. Replayed on 2026-09-29, as child processes one after the other, and compared in three parts (the answer, the callback timing, and the request lines without the CONNECT):
| Replayed against | Answers | Timing | Request lines | CLI answers | CLI request lines |
|---|---|---|---|---|---|
| 1.1.7, installed today | 90 of 90 | 90 of 90 | 90 of 90 | 20 of 20 | 20 of 20 |
| 2.0.0 | 56 of 90 | 71 of 90 | 73 of 90 | 10 of 20 | 17 of 20 (16 when a late request lands, below) |
The same numbers came out on Node 24.18.0 and Node 20.20.2, so the recording still stands for 1.1.7. The 34 answers that differ in 2.0.0 group like this:
| Calls | What 2.0.0 does | CHANGELOG line |
|---|---|---|
| 17 ids that are not post ids | throws TypeError, no request |
Changed: entityId must be a post id |
no callback, callback null
|
returns a Promise | Added: the Promise form |
| no arguments at all | the returned Promise rejects (1.1.7 threw) | Added: the Promise form, argument errors included |
| callback a string | throws TypeError, no request |
Changed: a callback that is not a function |
| callback that throws | called once | Fixed |
5 API errors (error_message), one of them with a throwing callback |
StackExchangeError, same message |
Changed: errors are StackExchangeError
|
| 4 bodies that are not JSON | StackExchangeError: The response is not JSON |
Changed: errors are StackExchangeError
|
| plain JSON body | read | Fixed |
| proxy refuses the tunnel (502) | TypeError: fetch failed |
Changed: network failures are the platform's errors |
| proxy drops the connection during the tunnel | no callback within the capture's 10-second wait | none (see below) |
Of the 19 timing differences, 17 are the refused ids, which now throw before any callback. One is the throwing callback's missing second call, and one is the dropped tunnel (below), which gave no callback within the capture's wait. Every callback that does run still runs after the call returns, as in 1.1.7. The 17 request differences are the 17 refused calls.
The 10 command line differences:
- the new help text, for
--helpand-h; -
--version, which 1.1.7 refused; -
-aand--answer, which now fetch the answer; - errors that now exit 1: an API error, letters as the id, a proxy refusing the tunnel;
- the plain-JSON body, now read;
- parseArgs' wording for an unknown option.
The one difference without a CHANGELOG line is the dropped tunnel. 1.1.7 called back at once with tunneling socket could not be established, cause=socket hang up. Under 2.0.0 Node's fetch sends the CONNECT again and again until the timeout; Edge cases and errors shows it. Sometimes one of those late requests reaches the stand-in during the next case, a command line run with no arguments, which then shows an extra request line. In the saved runs it happened on Node 20.20.2 (16 of 20) and not on Node 24.18.0 (17 of 20); an earlier run showed the opposite, so it is timing, not the Node line.
The copy run against 2.0.0 needed three changes, none to the cases:
- the bin's path read from
package.json(cli.jsbecamedist/cli.mjs); -
nonefor the dependencies 2.0.0 dropped (commander,request); - undici's
EnvHttpProxyAgentinstalled after the capture sets its proxy variables, and preloaded in its command line children.
The golden files were only read.
This wiki describes stack-exchange-markdown-retriever 2.0.0 and was last updated on 2026-09-29. The library is MIT licensed. Report problems in the issues. On npm: stack-exchange-markdown-retriever.
Using it
The releases
Contributing
Elsewhere