Docs/CoreTax Console
FOUGHT DOCUMENTATION

CoreTax Console

Chrome extension for automated tax invoice extraction from DJP CoreTax — XHR intercept, multi-sheet XLSX, and 7-sheet Inter Mode.

§ 01

CoreTax Console — Overview

Chrome Extension

ACTIVE

CoreTax Console is a Chrome Extension that automates tax document operations from the Indonesian DJP CoreTax system (coretax.pajak.go.id). It intercepts API responses, extracts tabular data, downloads PDFs, and generates multi-sheet XLSX exports — all without requiring manual page navigation or clicking.

CHROME MV3XHR INTERCEPTDOM CLICK7-SHEET XLSXAUTO RENAMEDUAL AUTH

Core Capabilities

FeatureDescriptionOutput
ExtractorExtract tabular data from CoreTax API responsesXLSX / CSV
Console (PDF Download)Download PDF invoices via XHR replay or DOM clickPDF files
Inter ModeExtract complete invoice details via /view endpoint replay7-sheet XLSX
Faktur Masukan Pipeline3-step pipeline: Scan → Extract → Download for input invoicesXLSX
Auto RenamerSmart filename renaming via data matching (not OCR)Renamed PDFs
PPh CalculatorBuilt-in PPh calculator injected into CoreTax pagesIn-page widget

Architecture — 4 Execution Contexts

The extension operates across four Chrome execution contexts, each with distinct capabilities. Communication flows through Chrome Extension APIs between contexts, and via window.postMessage between ISOLATED and MAIN worlds.

ContextWorldResponsibilities
Background Service WorkerExtensionMessage routing, job lifecycle, download tracking, state persistence, auth management
Sidepanel UIchrome://side-panelUser interface — Welcome, Console, Extractor, Faktur Masukan, Subscription, Settings
Content ScriptISOLATEDDOM manipulation, XHR bridge relay, FM handlers, capture-click logic
MAIN World ScriptsMAINXHR/fetch interception, pagination guard, confirm/alert bypass

3-Layer XHR Architecture

All XHR-based modes (Spam, Bot, Capture) use a 3-layer relay to bridge the gap between the Sidepanel and CoreTax's network requests:

┌─────────────────┐     chrome.runtime.sendMessage     ┌──────────────────┐     window.postMessage     ┌──────────────────┐
│  Sidepanel UI   │ ──────────────────────────────────► │  XHR Bridge      │ ─────────────────────────────► │  XHR Scraper     │
│  (chrome://     │     (xhr:* prefix messages)         │  (ISOLATED world)│  (FROM_CONTENT/FROM_PAGE)   │  (MAIN world)     │
│   side-panel)   │ ◄────────────────────────────────── │                  │ ◄─────────────────────────── │                  │
└─────────────────┘     response via sendResponse         └──────────────────┘     response via callback       └──────────────────┘

Layer 1 — Sidepanel:  User controls, export triggers, mode selection
Layer 2 — XHR Bridge:  Relay between Sidepanel ↔ MAIN world (ISOLATED)
Layer 3 — XHR Scraper: Intercepts XHR/fetch, replays requests, captures responses

Supported Data Sources

SourceList EndpointDetail EndpointDownloadInter Mode
OUTPUT_TAX/outputinvoice/list/outputinvoice/view
INPUT_TAX/inputinvoice/list/inputinvoice/view
OUTPUT_RETURN/outputreturn/list/outputreturn/view
INPUT_RETURN/inputreturn/list/inputreturn/view
SPECIAL_OUTPUT_TAX/specialdocumentoutputinvoice/list/specialdocumentoutputinvoice/view
SPECIAL_INPUT_TAX/specialdocumentinputinvoice/list/specialdocumentinputinvoice/view
DOC_MANAGEMENT/listTaxpayerDocuments
WITHHOLDING_SLIPS/GetMyWithholdingSlip/list
SPT_A2/returnsheetsportal
SPT_B2/returnsheetsportal
PPH_21/26/returnsheetsportal
§ 02

XHR Extraction Modes

Three Modes for Data Extraction

The Extractor provides three modes for retrieving tabular data from CoreTax API responses. All three operate via XHR interception — no manual page navigation or DOM clicking required. The same three modes also apply to PDF downloads via XHR replay (Inter mode).

Spam Mode

FASTEST

Auto-paginate through all data by replaying the captured XHR request with incrementing offset parameters and a large row count. The fastest way to extract bulk data — no DOM interaction at all.

ParameterValueNote
MethodXHR replay with modified First/Rows paramsReplays captured request
rows per request500 (E-Invoice), 100 (Doc Mgmt), 1000 (SPT/PPh)Varies by source payload size
Delay between requests100ms (E-Invoice), 150ms (others)Lightweight API calls
Error tolerance3 consecutive errorsStops after 3 consecutive failures
Warm cacheUsed for first page onlyReduces 1 redundant request

Bot Mode

CONTROLLED

Simulates sequential page navigation by clicking the "Next Page" button in the DOM, then capturing the XHR response that Angular generates. More controlled than Spam — each page is processed before moving to the next.

ParameterValueNote
MethodClick Next Page → capture XHR responseSimulates user pagination
Page detectionRow count < pageSize or duplicate dataAuto-stops at last page
Paginator wait100ms polling, 2000ms timeoutWaits for Angular to render
Error tolerance3 consecutive failuresSame as Spam Mode
Inter Mode integrationOptional — runs detail extraction per pageExtract then advance

Capture Mode

GRANULAR

Extract only the items you select. Check the rows you want in the CoreTax table, then run Capture Mode to extract just those items. Ideal for targeted extraction without processing the entire dataset.

ParameterValueNote
Matching strategyRow index (primary) + highlighted rows (fallback)Maps checked items to XHR data
ScopeSingle page onlyCheckbox state does not persist across pages
Warm cacheCritical — avoids re-clicking SearchUses 5-minute cached response
Checkbox preservationSnapshot before, restore afterUI unchanged after extraction

Mode × Source Compatibility

SourceSpamBotCaptureDownloadInterClick Mode
OUTPUT_TAX
INPUT_TAX
OUTPUT_RETURN
INPUT_RETURN
SPECIAL_OUTPUT_TAX
SPECIAL_INPUT_TAX
SPT_A2
SPT_B2
PPH_21/26
WITHHOLDING_SLIPS
DOC_MANAGEMENT
§ 03

DOM Click Mode

When XHR Replay Isn't Possible

FALLBACK

Some CoreTax download endpoints use CSRF tokens that change per request, making XHR replay impossible. DOM Click Mode handles these cases by physically clicking download buttons in the page — the same way a human would, but automated.

How It Works

Sub-ModeStrategyUse Case
Bot (Click)Click all download buttons per page, track tickets, navigate nextBulk PDF download for all items
Capture+ClickClick download buttons only for checked/selected itemsTargeted PDF download for specific items

Ticket-Based Download Tracking

Every button click creates a "ticket" tracked by the chrome.downloads API. The extension monitors onCreated and onChanged events to match each download to its ticket, ensuring no files are lost or double-counted.

// Download tracking flow
1. Click download button in DOM
2. Chrome creates download item → onCreated event
3. Match download URL/filename to pending ticket
4. Monitor onChanged → state: 'complete' | 'interrupted'
5. Mark ticket as done → proceed to next item

// Batch limit: 10 items per page (CLICK_BATCH_SIZE)
// Burst delay: progressive increase between batches

Self-Resume After Page Reload

Downloads can trigger page reloads in CoreTax. Capture+Click Mode persists its state to localStorage before each click. If the page reloads, the extension reads the saved state and resumes from the last unfinished item. State older than 5 minutes is considered stale and discarded.

// Self-resume mechanism
1. Before each click → save pending state to localStorage
2. On page load → check for saved state
3. If state exists and < 5 minutes old → resume
4. If state is stale → start fresh
5. After all items done → clear saved state

Downloadability Rules (E-Invoice)

Not all invoices have a downloadable PDF. The extension automatically skips items that would result in errors, saving time and bandwidth:

ConditionActionReason
Status = CREATEDSkipPDF not yet generated, no TaxInvoiceNumber, not e-Signed
CREDITED without DocFormAggIdSkipInvoice replaced by correction — PDF is obsolete
No DocFormAggId at allSkipCannot construct download URL without identifier
§ 04

Inter Mode — Detail Extraction

Complete Invoice Data in 7 Sheets

V2

Inter Mode combines list data with detail data from XHR replay to the /view endpoint, producing XLSX files with 7 sheets of complete invoice data — without navigating or clicking Edit. Available for all 6 e-invoice sources.

7-Sheet Output

SheetData SourceRecordsKey Fields
1. Ringkasan/list API1 per invoiceRecordId, NPWP, DPP, PPN, Status
2. Header Detail/view → Payload.*1 per invoiceAggregateVersion, InvoiceType, SellerTIN
3. Doc Transaksi/view → FormData.TransactionDocumentData1 per invoiceTransactionCode, SellerAddress
4. Data Pembeli/view → FormData.BuyerInformationData1 per invoiceBuyerTIN, IDDocument, Email
5. Detail Barang/view → FormData.TransactionDetailsData.Rows2-10x invoicesName, Qty, UnitPrice, VATRate
6. Ringkasan/Faktur/view → FormData.FooterRow1 per invoiceTotalPrice, TaxBaseTotal, VATTotal
7. Metadata/view → FormData top-level1 per invoiceIsDraft, IsMigrated

API Request Structure

POST /einvoiceportal/api/outputinvoice/view
{
  "RecordIdentifier": "<from list .RecordId>",
  "EinvoiceVATStatus": "VAT_VAT",
  "TaxpayerAggregateIdentifier": "<from list .Seller* or .Buyer* AggregateIdentifier>"
}

// Response: Payload.FormData is a JSON STRING — must parse twice
// Parse → extract TransactionDocumentData, BuyerInformationData,
//         TransactionDetailsData.Rows[], FooterRow, metadata

// Headers auto-captured:
//   content-type: application/json
//   languageid: id-ID
//   x-dgt-code: <auto-captured CSRF token>

Supported Sources

SourceDetail EndpointAggId SourceNon-Downloadable Status
OUTPUT_TAX/outputinvoice/viewSellerTaxpayerAggregateIdentifierCREATED
INPUT_TAX/inputinvoice/viewBuyerTaxpayerAggregateIdentifierCREDITED (no DocForm)
OUTPUT_RETURN/outputreturn/viewSellerTaxpayerAggregateIdentifierCREATED
INPUT_RETURN/inputreturn/viewBuyerTaxpayerAggregateIdentifierCREDITED (no DocForm)
SPECIAL_OUTPUT_TAX/specialdocumentoutputinvoice/viewSellerTaxpayerAggregateIdentifierCREATED
SPECIAL_INPUT_TAX/specialdocumentinputinvoice/viewBuyerTaxpayerAggregateIdentifierCREDITED (no DocForm)

Execution Parameters

ParameterValueNote
Delay between requests500msHeavier than list requests (100ms)
Max concurrent1 (serial)Sequential execution only
Error retry per item2xRetry twice before skip
Max consecutive errors5Abort entire job after 5 consecutive
Request timeout30 secondsSame as list requests
Session expiry (401/403)Immediate abortUser must re-login

Sheet Toggle Settings

All 7 sheets can be individually enabled or disabled. Toggle 1 (Ringkasan) controls whether the sheet appears in the output — but list data is always collected because RecordId and TaxpayerAggregateIdentifier are needed for /view API calls. If only Toggle 1 is active and Toggles 2–7 are off, the extension produces a list-only XLSX (no Inter Mode).

// Settings keys (all default: true)
interSheet1Ringkasan: true   // Sheet 1 — can be disabled
interSheet2Header: true      // Sheet 2
interSheet3DocData: true     // Sheet 3
interSheet4Buyer: true       // Sheet 4
interSheet5Items: true       // Sheet 5 — MOST IMPORTANT
interSheet6Footer: true      // Sheet 6
interSheet7Meta: true        // Sheet 7

Comparison: List Only vs Click Mode vs Inter Mode

AspectList OnlyClick Mode (DOM)Inter Mode (XHR)
Transaction item data
Full buyer info⚠️ Limited
Transaction document data
Per-invoice summary⚠️ Totals only
Metadata (draft, migrated)⚠️ Limited
Speed (151 invoices)~30 seconds~30+ minutes~2-3 minutes
Reliability✅ Stable API⚠️ DOM fragile✅ Stable API
Requires navigation
XLSX output1 sheet1 sheet (flat)7 sheets (relational)
§ 05

Faktur Masukan Pipeline

3-Step Pipeline for Input Invoices

PIPELINE

The Faktur Masukan (Input Invoice) pipeline is a specialized 3-step process for extracting data from invoices that don't have download buttons. It opens edit pages, extracts 21 columns of transaction data, and exports to XLSX with formula injection protection.

Pipeline Steps

Step 1: SCAN — Find invoices without download buttons
─────────────────────────────────────────────────
• Scan every row in the FM table
• Rows without #DownloadButton → marked as "pending"
• Bot mode: scan up to 500 pages
• Capture mode: scan current page only
• Output: pendingInvoices[]

Step 2: EXTRACT — Open edit pages and collect data
─────────────────────────────────────────────────
• For each pending invoice:
  1. Filter by invoice number in the search field
  2. Click the "Edit" button → navigate to edit page
  3. Wait for page to load (DOM polling, not sleep)
  4. Extract 14 columns of transaction rows
  5. Navigate back (history.back())
• Retry: 3 inner retries + 2 outer retries per invoice
• Output: excelRows[]

Step 3: DOWNLOAD — Build and save the XLSX file
─────────────────────────────────────────────────
• Build workbook with SheetJS (21 columns)
• Sanitize cells (formula injection + leading zero protection)
• Encode as base64 data URL (MV3 constraint)
• Trigger download via chrome.downloads API

XLSX Column Layout (21 Columns)

GroupColumnsSourceExamples
Metadata (7 cols)Tanggal, Masa Pajak, Nomor Faktur, Reference, Nama Penjual, Status, JenisList page rows01/06/2026, Juni 2026, 001.000.26.00000001
Detail (14 cols)Tipe, Nama, Kode, Kuantitas, Satuan, Harga Satuan, Total Harga, Potongan, Tarif PPN, DPP, PPN, DPP Nilai Lain, PPnBM, Tarif PPnBMEdit page rowsBarang, Jasa Konsultasi, 10, Unit, 1.234.567,89

Bot vs Capture Mode

AspectBot ModeCapture Mode
Scan scopeUp to 500 pagesCurrent page only
User steps3 clicks (Find → Extract → Download)1 click (Capture Excel — auto-extract & download)
Filter applicationRe-applies year/month filterSkips filter (already on right page)
SpeedSlower (multi-page navigation)Fast (single page)
Use caseBulk extraction of all pending invoicesQuick extraction of visible items

Data Protection

Table data unavailable
§ 06

Auto Renamer

Smart PDF Renaming via Data Matching

NOT OCR

The Auto Renamer renames downloaded PDF files by matching them against invoice data already captured by the extension — not by reading the PDF contents. This means renaming is instant, accurate, and works even with scanned or image-based PDFs.

How Data Matching Works

1. Extension monitors downloads from coretax.pajak.go.id
2. When a PDF download completes:
   a. Match the downloaded file to an invoice in the extracted data
   b. Use document type, invoice number, and other identifiers
   c. Rename the file based on matched data
3. Naming pattern varies by document type:
   • E-Invoice:  {InvoiceNumber}.pdf
   • Bukti Potong:  {BupotNumber}.pdf
   • Doc Management:  {DocType}_{Identifier}.pdf
4. Fallback: If no match found, keep original filename

Why Not OCR?

AspectData Matching (Our Approach)OCR-Based Renaming
SpeedInstant — matches against cached dataSlow — requires PDF parsing + text extraction
Accuracy100% for matched items — uses API dataVariable — depends on PDF quality, scan resolution
CoverageWorks with all PDFs (including scanned)Fails on image-only or low-quality scans
Resource usageMinimal — no PDF processing neededHigh — requires PDF library + OCR engine
DependenciesNone — uses already-captured dataRequires pdf.js or server-side OCR
§ 07

Authentication

Dual Authentication System

The extension uses two fully independent authentication systems. They never exchange tokens, never share credentials, and serve completely different purposes. You can use CoreTax features without Google login, and check your subscription without opening CoreTax.

SystemPurposeHow It Works
CoreTax SessionAccess DJP APIs for data extraction and PDF downloadsReuses browser session cookies + CSRF tokens automatically
Google Account (Fought Auth)Subscription management, company access, ad-free experienceGoogle OAuth via Chrome Identity API → JWT session token

CoreTax Session (Automatic)

No separate login required. The extension operates within your authenticated CoreTax browser session. All API requests reuse the credentials already present in the browser. Just make sure you're logged into CoreTax in the same tab.

CredentialSourcePurpose
Session cookiesBrowser cookie storeCoreTax API authentication
CSRF token (x-dgt-code)Auto-captured from XHR headersRequest validation for API calls
Access tokenIntercepted from fetch requestsJWT for CoreTax API authorization
Taxpayer IDlocalStorage.userinfoNPWP / taxpayer identification

Google Account (Fought Auth)

OAUTH

Sign in with Google to manage subscriptions and company access. The login flow uses Chrome's built-in Identity API — your Google credentials are never directly handled by the extension.

Table data unavailable

Security Measures

MeasureImplementation
Auth token storagechrome.storage.session — survives SW restart, clears on browser close
Rate limitingSliding window — 10 req/min for auth, 30 req/min for API
In-flight deduplicationMultiple concurrent /auth/me requests share one Promise
Session validationPeriodic server-side check with 2-minute grace period for new tokens
Auto signout401 from server triggers automatic cleanup of all auth data
§ 08

Access Tiers

Three-Tier Access System

TierHow ObtainedAdsExtractor AccessDonation UI
FreeDefault — no sign-up requiredProbability-based interstitial ads✅ AvailableVisible
SubscriberQRIS payment (Rp 100,000 / 30 days)Ad-free experience✅ AvailableVisible
CompanyB2B license via your organizationAd-free experience✅ AvailableHidden

All tiers have access to the same core features — Console, Inter Mode, Faktur Masukan, Auto Renamer. The only differences are ad presence and company-specific UI adjustments.

Access Hierarchy

hasFullAccess() = isCompanyUser() || isSubscriptionActive()

Priority order:
  1. Company User  → ALWAYS full access (highest priority)
                       No ads, no subscription needed, no donation UI
  2. Subscriber    → Full access until subscription expires
                       No ads, all features
  3. Free User     → All features with interstitial ads
                       Probability-based ad display

Company access takes priority over everything:
  • Even if subscription is expired → full access
  • Even if subscription is active → company badge shown
  • Admin can revoke company access at any time

Subscription via QRIS

Individual subscriptions are processed via QRIS (Quick Response Code Indonesian Standard), the standard QR payment method in Indonesia. Payment flow:

1. Click "Subscribe" in the sidepanel
2. Extension creates payment request → server generates QR code
3. Scan QR code with any Indonesian payment app (GoPay, OVO, Dana, etc.)
4. Payment confirmed via webhook (RSA-SHA256 verified)
5. Extension polls status → subscription activated automatically

Price:  Rp 100,000 (≈ US $6)
Period: 30 days
Identity: email_id (SHA-256 of normalized email)

Company Access

Company access is granted by your organization's administrator through a B2B license. Company users always get full access regardless of subscription status, see no ads, and the donation UI is automatically hidden. Company status is synced on extension install and browser startup — if an admin revokes access, it's reflected on next launch.

FOUGHT — DARK PRECISION V6.0
SYSTEMS ONLINE