qrtzcode
HomeDocsAPILeaderboardChangelog
Contribute
Docs

qrtzcode

Kumpulan gist & snippet pribadi — anime, AI tools, scraper, dan randomness.

Navigate

HomeDocsAPI Reference

Links

© 2026 qrtz. All snippets welcome.

ESC

Navigate

Links

Anime

animekuindo

Sraper animeku lengkap.

Creator

qrtz

Language

javascript

Views

24

Copies

9

Base

https://s2.animekuindo.life

Updated

23 Jun 2026

#anime#scraper

Code

249
animekuindo.js
const axios = require('axios');
const cheerio = require('cheerio');
const https = require('https');

const BASE_URL = 'https://s2.animekuindo.life';
let uaIndex = 0;

const userAgents = [
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0',
  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
  'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
  'Mozilla/5.0 (iPhone; CPU iPhone OS 17_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.6 Mobile/15E148 Safari/604.1'
];

function getHeaders(referer) {
  const ua = userAgents[uaIndex % userAgents.length];
  uaIndex++;
  return {
    'User-Agent': ua,
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
    'Accept-Language': 'id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7',
    'Accept-Encoding': 'gzip, deflate, br',
    'Referer': referer || BASE_URL + '/',
    'Sec-Ch-Ua': '"Not A(Brand";v="99", "Google Chrome";v="131", "Chromium";v="131"',
    'Sec-Ch-Ua-Mobile': '?0',
    'Sec-Ch-Ua-Platform': '"Windows"',
    'Sec-Fetch-Dest': 'document',
    'Sec-Fetch-Mode': 'navigate',
    'Sec-Fetch-Site': 'same-origin',
    'Sec-Fetch-User': '?1',
    'Upgrade-Insecure-Requests': '1',
    'Connection': 'keep-alive',
    'Cache-Control': 'max-age=0'
  };
}

async function fetchHTML(url) {
  const response = await axios({
    url,
    method: 'GET',
    headers: getHeaders(url),
    timeout: 30000,
    httpsAgent: new https.Agent({ rejectUnauthorized: false }),
    maxRedirects: 5,
    decompress: true,
    validateStatus: status => status >= 200 && status < 400
  });
  return response.data;
}

function clean(obj) {
  if (obj === null || obj === undefined) return undefined;
  if (Array.isArray(obj)) {
    const cleaned = obj.map(i => clean(i)).filter(i => i !== undefined);
    return cleaned.length ? cleaned : undefined;
  }
  if (typeof obj === 'object') {
    const result = {};
    for (const key of Object.keys(obj)) {
      const val = clean(obj[key]);
      if (val !== undefined) result[key] = val;
    }
    return Object.keys(result).length ? result : undefined;
  }
  return obj;
}

function decodeBase64Iframe(encoded) {
  try {
    const decoded = Buffer.from(encoded, 'base64').toString('utf-8');
    const match = decoded.match(/src=["']([^"']*)["']/);
    if (match) return match[1];
    return null;
  } catch {
    return null;
  }
}

class AnimekuindoScraper {
  constructor() {
    this.creator = 'rynaqrtz';
    this.baseUrl = BASE_URL;
  }

  async list(url) {
    const html = await fetchHTML(url);
    const $ = cheerio.load(html);

    const items = [];
    $('article.bs').each((i, el) => {
      const $el = $(el);
      const linkEl = $el.find('a').first();
      const link = linkEl.attr('href');
      const title = $el.find('.tt').text().trim() || linkEl.attr('title') || '';
      if (!link || !title) return;

      const poster = $el.find('img').first().attr('src') || null;
      const status = $el.find('.status').text().trim() || null;
      const type = $el.find('.typez').text().trim() || null;
      const epx = $el.find('.bt .epx').text().trim() || null;
      const sub = $el.find('.bt .sb').text().trim() || null;

      items.push({
        title,
        link: link.startsWith('http') ? link : this.baseUrl + link,
        poster,
        status,
        type,
        episode: epx,
        sub
      });
    });

    let next = null;
    const nextEl = $('.pagination .next, a.next.page-numbers');
    if (nextEl.length) next = nextEl.attr('href');

    const currentPage = parseInt($('.pagination .current, .page-numbers.current').text()) || 1;

    return clean({
      creator: this.creator,
      page: 'list',
      data: {
        url,
        count: items.length,
        currentPage,
        items,
        next: next ? (next.startsWith('http') ? next : this.baseUrl + next) : null
      }
    });
  }

  async home(page = 1) {
    const url = page === 1 ? this.baseUrl + '/' : this.baseUrl + `/page/${page}/`;
    return this.list(url);
  }

  async new(page = 1) {
    const url = page === 1 ? this.baseUrl + '/anime-baru-dirilis/' : this.baseUrl + `/anime-baru-dirilis/page/${page}/`;
    return this.list(url);
  }

  async top(page = 1) {
    const url = page === 1 ? this.baseUrl + '/top-rating/' : this.baseUrl + `/top-rating/page/${page}/`;
    return this.list(url);
  }

  async search(query, page = 1) {
    const url = page === 1
      ? this.baseUrl + `/?s=${encodeURIComponent(query)}`
      : this.baseUrl + `/page/${page}/?s=${encodeURIComponent(query)}`;
    return this.list(url);
  }

  async genresList() {
    const html = await fetchHTML(this.baseUrl + '/genres/');
    const $ = cheerio.load(html);
    const items = [];
    $('ul.taxindex li a').each((i, el) => {
      const $el = $(el);
      const name = $el.find('.name').text().trim();
      const count = $el.find('.count').text().trim();
      const link = $el.attr('href');
      if (name && link) {
        items.push({
          name,
          count: count ? parseInt(count) : null,
          link: link.startsWith('http') ? link : this.baseUrl + link
        });
      }
    });
    return clean({
      creator: this.creator,
      page: 'genres_list',
      data: { url: this.baseUrl + '/genres/', count: items.length, items }
    });
  }

  async genre(slug, page = 1) {
    const url = page === 1
      ? this.baseUrl + `/genres/${slug}/`
      : this.baseUrl + `/genres/${slug}/page/${page}/`;
    return this.list(url);
  }

  async schedule() {
    const html = await fetchHTML(this.baseUrl + '/jadwal/');
    const $ = cheerio.load(html);
    const schedule = {};

    $('.schedulepage').each((i, el) => {
      const $el = $(el);
      const dayHeader = $el.find('.releases h3 span').text().trim();
      if (!dayHeader) return;
      const day = dayHeader.toLowerCase();

      const items = [];
      $el.find('.bs').each((j, item) => {
        const $item = $(item);
        const linkEl = $item.find('a').first();
        const link = linkEl.attr('href');
        const title = $item.find('.tt').text().trim() || '';
        const time = $item.find('.cndwn').text().trim() || null;
        const img = $item.find('img').first().attr('src') || null;
        if (link) {
          items.push({
            title,
            link: link.startsWith('http') ? link : this.baseUrl + link,
            time,
            poster: img
          });
        }
      });
      schedule[day] = items;
    });

    return clean({
      creator: this.creator,
      page: 'schedule',
      data: { url: this.baseUrl + '/jadwal/', schedule }
    });
  }

  async detail(slug) {
    const url = slug.startsWith('http') ? slug : this.baseUrl + '/anime/' + slug.replace(/^\/+/, '');
    const html = await fetchHTML(url);
    const $ = cheerio.load(html);

    const title = $('h1.entry-title').text().trim() || $('h1[itemprop="name"]').text().trim() || '';
    const poster = $('.thumb img, .thumbook .thumb img').first().attr('src') || null;

    let rating = null;
    const ratingText = $('.rating strong').text().trim();
    if (ratingText) {
      const match = ratingText.match(/([\d.]+)/);
      if (match) rating = parseFloat(match[1]);
    }

    const info = {};
    $('.spe span').each((i, el) => {
      const text = $(el).text().trim();
      const parts = text.split(':');
      if (parts.length >= 2) {
        const label = parts[0].trim().toLowerCase();
        const value = parts.slice(1).join(':').trim();
        if (label && value) info[label] = value;
      }
    });

    const status = info['status'] || null;
    const studio = info['studio'] || null;
    const released = info['dirilis'] || null;
    const duration = info['durasi'] || null;
    const season = info['season'] || null;
    const country = info['negara'] || null;
    const type = info['tipe'] || null;
    const totalEps = info['episode'] || null;
    const producers = info['producers'] || null;
    const casts = info['casts'] || null;

    const genres = [];
    $('.genxed a').each((i, el) => {
      genres.push($(el).text().trim());
    });

    let synopsis = null;
    $('.desc, .synopsis, .entry-content p').each((i, el) => {
      const text = $(el).text().trim();
      if (text && text.length > 50 && !text.includes('Show more')) {
        synopsis = text;
        return false;
      }
    });

    const episodes = [];
    $('.eplister ul li a').each((i, el) => {
      const $el = $(el);
      const link = $el.attr('href');
      const num = $el.find('.epl-num').text().trim() || null;
      const title = $el.find('.epl-title').text().trim() || null;
      const date = $el.find('.epl-date').text().trim() || null;
      if (link) {
        episodes.push({
          number: num,
          title,
          url: link.startsWith('http') ? link : this.baseUrl + link,
          date
        });
      }
    });

    const firstEp = episodes.length > 0 ? episodes[episodes.length - 1] : null;
    const lastEp = episodes.length > 0 ? episodes[0] : null;

    return clean({
      creator: this.creator,
      page: 'detail',
      data: {
        url,
        slug,
        title,
        poster,
        rating,
        status,
        studio,
        released,
        duration,
        season,
        country,
        type,
        totalEps,
        producers,
        casts,
        genres,
        synopsis,
        episodes,
        firstEpisode: firstEp,
        lastEpisode: lastEp
      }
    });
  }

  async episode(url) {
    const html = await fetchHTML(url);
    const $ = cheerio.load(html);

    const title = $('h1.entry-title').text().trim() || '';
    const poster = $('.tb img').first().attr('src') || null;
    const seriesName = $('.infolimit h2').text().trim() || null;
    const altTitle = $('.alter').text().trim() || null;
    const rating = $('.rating strong').text().trim() || null;
    const status = $('.spe span:contains("Status")').text().trim() || null;
    const studio = $('.spe span:contains("Studio") a').text().trim() || null;
    const type = $('.epx').text().trim() || null;
    const released = $('.year .updated').text().trim() || null;

    let iframeUrl = null;
    let videoUrl = null;

    $('.player-embed iframe').each((i, el) => {
      const src = $(el).attr('src');
      if (src) {
        iframeUrl = src;
        videoUrl = src;
        return false;
      }
    });

    if (!iframeUrl) {
      $('select.mirror option').each((i, el) => {
        const value = $(el).attr('value');
        if (value) {
          const decoded = decodeBase64Iframe(value);
          if (decoded) {
            iframeUrl = decoded;
            videoUrl = decoded;
            return false;
          }
        }
      });
    }

    if (!videoUrl) {
      $('video source').each((i, el) => {
        const src = $(el).attr('src');
        if (src) {
          videoUrl = src;
          return false;
        }
      });
    }

    let prevEpisode = null;
    const prevEl = $('.nvs a:contains("Prev")');
    if (prevEl.length) prevEpisode = prevEl.attr('href');

    let nextEpisode = null;
    const nextEl = $('.nvs a:contains("Next")');
    if (nextEl.length) nextEpisode = nextEl.attr('href');

    const episodeList = [];
    $('#singlepisode .episodelist ul li a').each((i, el) => {
      const $el = $(el);
      const link = $el.attr('href');
      const title = $el.find('h3').text().trim() || '';
      const info = $el.find('span').text().trim() || '';
      if (link) {
        episodeList.push({
          title,
          url: link.startsWith('http') ? link : this.baseUrl + link,
          info
        });
      }
    });

    return clean({
      creator: this.creator,
      page: 'episode',
      data: {
        url,
        title,
        poster,
        seriesName,
        altTitle,
        rating,
        status,
        studio,
        type,
        released,
        videoUrl,
        iframeUrl,
        prevEpisode: prevEpisode ? (prevEpisode.startsWith('http') ? prevEpisode : this.baseUrl + prevEpisode) : null,
        nextEpisode: nextEpisode ? (nextEpisode.startsWith('http') ? nextEpisode : this.baseUrl + nextEpisode) : null,
        episodeList
      }
    });
  }
}

if (require.main === module) {
  const args = process.argv.slice(2);
  const command = args[0];
  const params = args.slice(1);
  const scraper = new AnimekuindoScraper();

  (async () => {
    let result;
    try {
      switch (command) {
        case 'home':
          result = await scraper.home(parseInt(params[0]) || 1);
          break;
        case 'new':
          result = await scraper.new(parseInt(params[0]) || 1);
          break;
        case 'top':
          result = await scraper.top(parseInt(params[0]) || 1);
          break;
        case 'search':
          if (!params[0]) throw new Error('Query required');
          result = await scraper.search(params[0], parseInt(params[1]) || 1);
          break;
        case 'genres':
          result = await scraper.genresList();
          break;
        case 'genre':
          if (!params[0]) throw new Error('Genre slug required');
          result = await scraper.genre(params[0], parseInt(params[1]) || 1);
          break;
        case 'schedule':
          result = await scraper.schedule();
          break;
        case 'detail':
          if (!params[0]) throw new Error('Slug or URL required');
          result = await scraper.detail(params[0]);
          break;
        case 'episode':
          if (!params[0]) throw new Error('URL required');
          result = await scraper.episode(params[0]);
          break;
        default:
          console.error(`Unknown command: ${command}`);
          console.log(`
Commands:
  home [page]                    - Homepage
  new [page]                     - Anime baru dirilis
  top [page]                     - Top rating
  search <query> [page]          - Search anime
  genres                         - List all genres
  genre <slug> [page]            - Filter by genre
  schedule                       - Jadwal rilis
  detail <slug|url>              - Detail anime + episode list
  episode <url>                  - Get video URL (auto-decode)
          `);
          process.exit(1);
      }
      console.log(JSON.stringify(result, null, 2));
    } catch (err) {
      console.error(JSON.stringify({ error: err.message }));
      process.exit(1);
    }
  })();
}

module.exports = AnimekuindoScraper;

Rating

4.0(1)

Gimana snippet ini menurutmu?

</> Embed

Embed ke website / blog

<iframe src="https://qrtzcode.vercel.app/api/embed/anime/animekuindo" style="width:100%;height:400px;border:none;border-radius:12px;"></iframe>

Related Snippets

otakudesu

seperti biasa bebas kalian modifikasi ubah credit ama creatornya, ak gabakal baper kok😹, semoga bermanfaat ya^^.

66
37

nimegami

Semoga bermanfaat^^.

35
11

oploverz

kalo ad bug benerin ajh sendiri.

9
7