Operations

Does your rich text editor phone home? How to check

Metered editors need to count you. If your editor bills per load, something is reporting those loads. A ten-minute method to find out exactly what your editor sends, and where.

7 min read

“Self-hosted” is not a binary. An editor can ship as files you serve from your own domain and still call out to a vendor endpoint to validate a licence, report usage, or fetch a remote asset. If a product is billed per editor load, something has to count those loads.

This is straightforward to check, and you should check it yourself rather than take anyone’s word for it — including ours. Here is a method that takes about ten minutes and produces evidence you can put in a security review.

Why it matters beyond licensing

The method: instrument before you load

The DevTools Network panel shows you resource loads, but it is easy to miss a single beacon fired during teardown, and hard to attach a call to the code that made it. A more reliable approach is to wrap the three outbound APIs before the editor script is parsed, so nothing can slip past.

The order matters: this block has to come before the editor’s <script> tag.

<script>
window.__net = [];
(function () {
  var of = window.fetch;
  if (of) window.fetch = function (u) {
    window.__net.push({ how: 'fetch', url: String((u && u.url) || u) });
    return of.apply(this, arguments);
  };

  var oo = XMLHttpRequest.prototype.open;
  XMLHttpRequest.prototype.open = function (m, u) {
    window.__net.push({ how: 'xhr', method: m, url: String(u) });
    return oo.apply(this, arguments);
  };

  var sb = navigator.sendBeacon && navigator.sendBeacon.bind(navigator);
  if (sb) navigator.sendBeacon = function (u) {
    window.__net.push({ how: 'beacon', url: String(u) });
    return sb.apply(navigator, arguments);
  };
})();
</script>

<!-- editor scripts go AFTER the block above -->
<script src="/path/to/editor.js"></script>

sendBeacon is the one people forget. It exists specifically to send analytics during page unload, it is fire-and-forget, and it is easy to miss if you are watching a network panel while clicking around.

Exercise the editor, then read the log

Loading the page is not enough — some calls only fire on first edit, on focus, or on teardown. Do a realistic pass: set content, run a few commands, type, then read the log.

// after interacting with the editor
var calls = window.__net;
var external = calls.filter(function (c) {
  return /^https?:\/\//i.test(c.url) && c.url.indexOf(location.origin) !== 0;
});

console.table(calls);
console.log('external calls:', external);

Filtering on location.originis the important step. Same-origin requests are your own server — image uploads, autosave endpoints, your API. What you are looking for is anything leaving your origin that you did not configure.

Reading the results honestly

Not every external request is a problem. Sort what you find into three buckets:

Test the configuration you will actually ship. An editor with AI, collaboration and cloud uploads switched on legitimately talks to those services. The meaningful question is what a default, self-hosted setup does with no integrations configured.

What this produces for RichTextEditor

Running exactly the method above against a default self-hosted setup — instrument, load the editor, set content, run commands, dispatch input events — produces an empty log: no fetch, no XMLHttpRequest, no sendBeacon, and no external resource loads. The only requests are the local editor assets you are serving and inline data: URIs.

That is a consequence of the licensing model rather than a feature we bolted on: a perpetual, unmetered licence has nothing to count, so there is no counter to phone home. Optional integrations, once you configure them, obviously talk to the services you point them at.

Run it against whichever editors are on your shortlist. It is the same ten minutes for each, and the output is evidence rather than a marketing claim — which is the point.


RichTextEditor is a perpetual-licence JavaScript editor — one purchase, self-hosted, no metered editor loads. Download the evaluation or see how it compares.