EcoMeter AI has a single purpose: to read AI chat conversations already displayed in your browser and estimate the number of tokens, monetary cost, and water consumption associated with those conversations. All analysis is performed locally on your device. The extension has no secondary purpose.
api.anthropic.com/v1/messages/count_tokens) for Claude, or,
if you add a Google key, Google's
(generativelanguage.googleapis.com/…:countTokens) for Gemini. Both
are off unless you opt in, and each sends the same text you are already
sending to that AI. No other external connections are made under any circumstances.chrome.storage.session (cleared automatically when the browser closes) and
your model preference in chrome.storage.local (persisted on your device only).Conversation text (read-only, stays on device). The extension uses a content script running inside your browser tab to read the visible text of AI chat pages you are already viewing — the same text you can see on screen. This text is used only to count tokens locally and is never transmitted anywhere. It is not written to disk and is discarded when the page is navigated away from or the browser is closed.
Anthropic API key (optional, session-only).
If you choose to enter an Anthropic API key, it is stored using
chrome.storage.session. Session storage is ephemeral: it is held
in memory only for the duration of the current browser session and is
automatically cleared when the browser closes. The key is never written to
persistent storage and never synced to any remote server. It is used solely to
call Anthropic's official token-counting endpoint
(api.anthropic.com/v1/messages/count_tokens) on your behalf,
using the message text already present in your browser — no conversation data
is stored by this call. You can remove the key at any time using the
"remove key" button in the panel.
Google (Gemini) API key (optional, off by default, session-only).
If you choose to add a Google AI API key for exact Gemini token counts, it is stored the same
way as the Anthropic key — chrome.storage.session, in memory only, cleared when
the browser closes, never written to persistent storage and never synced anywhere. It is used
solely to call Google's official token-count endpoint
(generativelanguage.googleapis.com/v1beta/models/…:countTokens) with your
own message text — the same content you are already sending to Gemini. This feature is
off unless you add the key, and you can remove it any time with "Clear" in
the "Exact token counts" panel.
Model preference (local device only).
Your selected AI model is stored in chrome.storage.local, which
keeps data on your device only and never syncs it to Google's servers or any
other remote server. This preference is never transmitted anywhere.
Usage tracking (optional, off by default, local only).
The Subscription Auditor at legerlyai.com can suggest the plan that fits your real
usage. To support that, the panel has an opt-in "Usage tracking" switch that
is off by default. When you turn it on, the extension keeps a running
tally — on your device only, in chrome.storage.local — of how many
messages and tokens you use per platform and per model. It stores
counts only; no message content is kept (text is used transiently to
count tokens, then discarded). This data is never transmitted.
How the tally reaches the Subscription Auditor — no upload is involved. The connection between the extension and the Auditor is a file you move yourself, deliberately, in three steps. Nothing happens automatically and nothing is sent anywhere:
ecometer-usage.json) to your own downloads folder. This is a local
file save — no network request is made, and the file is not sent to Legerly or anyone else.FileReader, to pre-fill the questionnaire. The file is
never transmitted to a server — not to Legerly, not to anyone. The Auditor
is a static page with no backend that could receive it.The exported file contains counts only — messages, tokens, models used, and days tracked. It contains no message content. You can inspect it in any text editor before you use it, and you can erase the underlying tally at any time with “Clear history”, by turning the switch off, or via “remove key” (logout). Leave the switch off and none of this is recorded in the first place.
Active tab identity (not stored, not transmitted). When the user clicks the extension icon, the browser grants temporary access to the active tab's numeric ID. This ID is stored in session memory solely to route messages between the side panel and the content script on that tab. The tab URL is not read, stored, or transmitted by the extension.
When no API key is provided the extension makes zero network requests. All fonts, scripts, and pricing data are bundled inside the extension package; no content is loaded from external servers at runtime.
When you provide an API key, the extension makes external connections to that provider's official token-counting endpoint only, using your own key:
api.anthropic.com/v1/messages/count_tokens) —
only when you have entered an Anthropic API key, and only for Claude conversations.
Governed by Anthropic's Privacy Policy.generativelanguage.googleapis.com/v1beta/models/…:countTokens) —
only when you have entered a Google AI API key, and only for Gemini conversations.
Governed by Google's Privacy Policy.Each key is independent: entering one does not enable the other, and neither is required to use the extension. In both cases only the text of your own messages is sent — AI responses are counted locally and never transmitted, and no message content is stored or sent anywhere else. Beyond these two endpoints, and only when the corresponding key is present, the extension makes no external connections under any circumstances.
The following table explains exactly why each permission is required. No permission is requested beyond what is necessary for the single stated purpose.
| Permission | Why it is required |
|---|---|
| storage | Stores your model preference, setup state, and (if you opt in) your
local usage tally in chrome.storage.local, and any optional
API keys in chrome.storage.session — all on your device
only. No data is synced remotely. |
| sidePanel | Required to open and render the side panel UI in which token counts and cost estimates are displayed. |
| activeTab | Grants temporary access to the currently-focused tab when the user
clicks the extension icon. Used solely to open the side panel for
that tab. The tab's URL is not read by the extension.
Unlike the broader tabs permission, activeTab
does not expose other open tabs. |
| scripting | Required to programmatically inject the content script into
x.com tabs that are navigated to the Grok chat path
(x.com/grok or x.com/i/grok).
Injection is path-gated: the script is never injected on any
other x.com page. This avoids declaring a broad
x.com/* host permission for the whole domain. |
| Host: api.anthropic.com | Required only when the user provides an Anthropic API key. Used solely to call Anthropic's official token-counting API on the user's behalf, so that Claude token counts are exact rather than estimated. Only the user's own message text is sent. No request is made without an explicit API key. |
| Host: generativelanguage.googleapis.com | Required only when the user provides a Google AI API key, which is
optional and off by default. Used solely to call Google's official
countTokens endpoint on the user's behalf, so that Gemini
token counts are exact rather than estimated. Only the user's own
message text is sent. No request is made without an explicit API key,
and this permission is unused for every other platform. |
| Host: claude.ai, chatgpt.com, chat.openai.com, gemini.google.com, grok.com, chat.mistral.ai, perplexity.ai, www.perplexity.ai, copilot.microsoft.com, poe.com, chat.deepseek.com | Required to inject the content script that reads visible
conversation text on each supported AI platform. Access is limited
to these specific domains only. x.com is handled via the
scripting permission above (path-gated injection)
rather than a blanket host permission. No other websites are
accessed. |
Conversation text is held in memory only for the duration of the active browser session and is never written to disk. It is discarded when the panel is closed or the page is navigated away from.
Your Anthropic API key is stored in chrome.storage.session and is
automatically cleared when the browser closes. It does not persist between
browser sessions.
Your model preference is stored in chrome.storage.local until you
click "remove key" in the panel, which clears all locally stored data including
your model preference, setup state, and internal version marker.
This extension does not knowingly collect any information from children under 13. It does not collect personal information from any user of any age.
If this privacy policy is updated, the new version will be published at this URL and the effective date above will be updated. Continued use of the extension after a policy change constitutes acceptance of the updated policy.
For questions or concerns about this privacy policy, please open an issue on the extension's GitHub repository.