Skip to content

Getting Started

Need a view counter for a GitHub README, blog, or personal site? Tally API gives you a hosted counter endpoint with no signup and no backend to manage. If you prefer, you can also deploy the same stack to your own Cloudflare account.

Why Tally API

Tally API started as a simpler replacement for a counter stack built around LeanCloud, MongoDB Atlas, and Moe Counter. When LeanCloud announced the end of its public service in January 2026, moving the storage layer to Cloudflare KV became the cleaner long-term option.

Unlike Moe Counter, Tally API also exposes JSON. You can keep the familiar SVG badge for Markdown, or build your own UI around the raw count.

URL Structure

The API follows this format:

text
https://tally.yuki.sh/hits/:id/:resource[.format]
  • :id is your namespace
  • :resource is the counter name inside that namespace

If you want to track visits to a GitHub README, you might use:

http
https://tally.yuki.sh/hits/github/readme

If you want to track a blog post, for example https://blog.yuki.sh/posts/976864126ca2, you could use:

http
https://tally.yuki.sh/hits/blog/976864126ca2

The public instance runs on a shared domain, so choose a namespace that is unlikely to collide with someone else's. A pattern like github@yourname works well, for example /hits/github@xueelf/readme.

If you would rather not rely on a shared service, follow the Deploy guide and run your own instance.

Read Counts as JSON

You can request JSON directly:

http
GET https://tally.yuki.sh/hits/docs/tally-api.json

The .json suffix is optional. If you omit it, the API still returns JSON by default. The response includes both the total hit count and the number of unique client IPs:

typescript
type Response = {
  visit: number;
  visitor: number;
};

That makes Tally API easy to integrate into your own components. The box below is rendered from a live API request:

Loading...

Full component source:

vue
<script setup lang="ts">
import { onMounted, ref } from 'vue';

const API = 'https://tally.yuki.sh/hits/docs/tally-api';
const visit = ref<number | null>(null);
const visitor = ref<number | null>(null);
const isFailed = ref(false);

onMounted(async () => {
  try {
    const response = await fetch(API);

    if (!response.ok) {
      throw new Error('Request failed');
    }
    const data: { visit: number; visitor: number } = await response.json();

    visit.value = data.visit;
    visitor.value = data.visitor;
  } catch {
    isFailed.value = true;
  }
});
</script>

<template>
  <div class="count-card">
    <span v-if="isFailed">Failed to fetch count.</span>
    <span v-else-if="visit === null">Loading...</span>
    <span v-else>Total API Hits: {{ visit }} / Unique IPs: {{ visitor }}</span>
  </div>
</template>

<style scoped>
.count-card {
  padding: 20px 24px;
  border-radius: 8px;
  background-color: var(--vp-code-block-bg);
}
</style>

Embed as SVG

If all you need is a counter badge in Markdown, SVG is the simplest option:

md
![counter](https://tally.yuki.sh/hits/docs/tally-api.svg)

Preview:

counter

You can switch themes with a query parameter:

md
![counter](https://tally.yuki.sh/hits/docs/tally-api.svg?theme=miku)

For example:

counter

Tally API supports every Moe Counter theme, including moebooru, gelbooru, miku, and minecraft. See https://count.getloli.com for the full gallery.

If you want the image itself to be clickable, wrap it in a link:

md
[![counter](https://tally.yuki.sh/hits/docs/tally-api.svg)](https://github.com/xueelf/tally-api)

Next Steps

For request rules, response formats, and error cases, continue with API Reference.