$132,900 Foreign Earned Income Exclusion: Tracking the Physical Presence Test in Your Ledger

I’ve been helping a friend who went nomadic last year get their Beancount setup ready for tax season, and it’s been a real education in tracking the Foreign Earned Income Exclusion requirements.

The 330-Day Reality Check

The IRS requires 330 full days in foreign countries during any 12-month period to claim the FEIE. For 2026, that’s up to $132,900 of earned income you can exclude from US taxes. But here’s the catch that trips people up: a “full day” means midnight to midnight in a foreign country. That travel day when you landed in Barcelona at 2pm? Doesn’t count toward your 330.

A Beancount Metadata Approach

Here’s what we came up with using custom metadata and events:

; Physical Presence Test Tracking
; Tax Year: 2026
; Qualifying Period: 2025-03-15 to 2026-03-14

2026-01-15 * "Client Invoice - Web Development"
  Income:Freelance:Consulting  -4500 USD
  Assets:Bank:Wise:USD          4500 USD
    location: "Lisbon, Portugal"
    presence-date: "2026-01-15"
    presence-status: "foreign"

For border crossings, tracking separately with events:

2026-02-10 event "travel" "Departure: Lisbon -> Miami (Travel Day - Partial)"
  ; Arrival 6pm local time - this day does NOT count
  
2026-02-11 event "travel" "Arrival: Miami, USA"
  ; Full day in USA - does not count toward 330 days
  
2026-02-18 event "travel" "Departure: Miami -> Mexico City"
  ; Travel day - partial
  
2026-02-19 event "travel" "First full day: Mexico City, Mexico"
  ; First FULL day in Mexico starts midnight tonight

The Query That Matters

A custom bean-query to count qualifying days:

SELECT 
  YEAR(date) as year,
  meta("location") as location,
  COUNT(date) as days
WHERE 
  account ~ "Income" 
  AND meta("presence-status") = "foreign"
GROUP BY year, location
ORDER BY days DESC

Documentation Beyond Beancount

The ledger tracks the pattern, but you’ll want supporting docs:

  • Flight confirmations (PDF saved with dates/times)
  • Apartment lease agreements (proves foreign residence)
  • Coworking space receipts (shows where you were working)
  • Passport stamps (photographed, though not all countries stamp anymore)

Questions for the Community

  1. Has anyone found a cleaner way to track travel days vs. full presence days in Beancount?
  2. Are you tracking this at the transaction level or maintaining a separate presence log file?
  3. For those who’ve been audited on FEIE claims, what documentation did the IRS actually want to see?

The edge cases worry me most - like flights crossing midnight, or being in international waters. How are others handling these?

References: IRS Physical Presence Test, 2026 FEIE Limit

This is a great starting point, but I’d add a few things from the tax professional side.

The 12-Month Period Flexibility

One thing people don’t realize: you get to choose your 12-month qualifying period. It doesn’t have to match the calendar year. The IRS lets you pick the consecutive 12-month period that gives you the greatest exclusion. This is huge for people who started traveling mid-year.

For someone who left the US on March 15, 2025, their optimal period might be March 15, 2025 to March 14, 2026 - which spans two tax years but maximizes their foreign days in each.

Your Beancount setup should track:

option "title" "Physical Presence Test - Multiple Periods"

; Track each potential 12-month period
custom 2025-03-15 "feie-period-start" "Period A: 2025-03-15 to 2026-03-14"
custom 2025-06-01 "feie-period-start" "Period B: 2025-06-01 to 2026-05-31"

The Bona Fide Residence Alternative

Also worth mentioning: the Physical Presence Test isn’t the only path to FEIE. The Bona Fide Residence Test works if you’ve established true residence in a foreign country. That requires different documentation - local tax filings, bank accounts, lease agreements. Some nomads actually find this easier if they pick a “home base” country.

What IRS Actually Looks For

I’ve helped clients through FEIE audits. The IRS wanted:

  1. Passport with entry/exit stamps (or explanation why stamps are missing)
  2. Bank/credit card statements showing foreign transactions
  3. Lease agreements or hotel receipts
  4. Flight itineraries with timestamps
  5. Employer letters confirming work location

Your Beancount location metadata is great for organizing this evidence, but keep the source documents accessible.

I went through this exact exercise last year and ended up building a small Python script that generates a presence log from my Beancount events. Wanted to share a different approach that’s worked well.

Dedicated Presence Tracking File

Instead of attaching metadata to income transactions, I keep a separate presence.beancount file that only tracks location:

; presence.beancount - Physical location tracking for FEIE

2026-01-01 custom "location" "Mexico City, Mexico" "full-day"
2026-01-02 custom "location" "Mexico City, Mexico" "full-day"
; ... daily entries ...
2026-01-15 custom "location" "IN-TRANSIT" "partial"  ; Flight CDMX->LAX
2026-01-15 custom "location" "Los Angeles, USA" "arrival"
2026-01-16 custom "location" "Los Angeles, USA" "full-day"

The Python Script

#!/usr/bin/env python3
"""
feie_calculator.py - Count qualifying days for Physical Presence Test
"""
import beancount.loader
from beancount.core import data

def count_foreign_days(entries, start_date, end_date):
    foreign_days = 0
    us_days = 0
    partial_days = 0
    
    for entry in entries:
        if isinstance(entry, data.Custom) and entry.type == "location":
            if start_date <= entry.date <= end_date:
                location = entry.values[0].value
                day_type = entry.values[1].value if len(entry.values) > 1 else "full-day"
                
                if day_type == "full-day" and "USA" not in location:
                    foreign_days += 1
                elif "USA" in location:
                    us_days += 1
                else:
                    partial_days += 1
    
    return foreign_days, us_days, partial_days

This gives me a clear count I can run against any 12-month window.

Edge Cases I’ve Handled

  • Midnight flights: If you depart Bangkok at 11pm and land in Tokyo at 6am, neither day counts as a “full day” in either country. I mark both as “partial”.
  • International waters: Not foreign soil, doesn’t count. Cruise ship days get marked separately.
  • Layovers: A 6-hour layover in Dubai doesn’t count as being “in” the UAE for FEIE purposes.

The key insight: keep your presence tracking separate from your financial transactions. They’re related but distinct concerns, and you’ll thank yourself when tax time comes.

Living this right now as a consultant splitting time between Europe and Asia. A few things I’ve learned the hard way:

Multi-Currency Makes It More Complex

When you’re earning in USD, spending in THB, and paying taxes in your home country, the FEIE is just one piece of the puzzle. I track my presence alongside currency exposure:

2026-01-20 * "Coworking Day Pass" "KoHub, Koh Lanta"
  Expenses:Office:Coworking  450 THB @ 0.029 USD
  Assets:Bank:Bangkok:THB
    location: "Thailand"
    presence-status: "foreign"

This lets me run queries that show both my day count AND my currency exposure by location.

The “Tax Home” Trap

One thing that caught me off guard: claiming FEIE can trigger the “no tax home” penalty. If you’re truly nomadic with no permanent residence anywhere, the IRS may say you don’t have a tax home abroad - and you can’t deduct housing costs.

The workaround is establishing a clear “tax home” in one foreign location, even if you travel frequently. I use my long-term lease in Chiang Mai as my official foreign tax home, even though I’m only there ~4 months/year.

Google Timeline Is Your Friend

For those worried about documentation gaps - if you have an Android phone or use Google Maps, your Location History is available at timeline.google.com. It’s admissible for tax purposes and fills in gaps when you forgot to save that flight receipt.

I export my timeline quarterly and reconcile it against my Beancount presence log. They should match. When they don’t, I investigate.

One Warning

Be careful not to double-dip. If you claim FEIE on income, you can’t also deduct the foreign taxes you paid on that same income via the Foreign Tax Credit. You have to choose. For most nomads in low-tax countries, FEIE is the clear winner. But run the numbers if you’re in a high-tax jurisdiction like Germany or Japan.

This thread is gold - saving it for when I finally pull the trigger on going remote full-time.

Quick clarifying questions from someone who hasn’t done this yet:

1. What about Schengen countries?
If I’m bouncing between Portugal, Spain, and Germany (all Schengen), do I need separate documentation for each country, or does the Schengen entry stamp cover it? The 90/180 rule limits my time anyway, but I want to make sure I’m tracking correctly.

2. Housing exclusion in addition to FEIE?
@accountant_alice mentioned the tax home issue. But isn’t there also a separate Foreign Housing Exclusion on top of the $132,900? If I’m paying $2,000/month rent in Lisbon, can I exclude that too?

3. The “abode” question
The IRS Form 2555 asks if you maintained an “abode” in the US. If I still have a storage unit with my stuff in the States, or my parents’ address on my driver’s license, does that disqualify me?

4. Quarterly estimated taxes?
If I’m expecting to exclude all my income under FEIE, do I still need to pay quarterly estimated taxes while abroad? Or can I wait until I file?

Sorry for all the questions - this is way more nuanced than I expected. Appreciate everyone sharing their experience.