Best Time Tracking Tools That Actually Work for Freelancers
1. Harvest consistently fails to recognize paused timers correctly
If I had a nickel for every time Harvest logged 18 hours because I forgot to stop a timer, I’d have enough to pay for Toggl. This one’s brutal if you multitask across tabs. The UI shows the timer as paused, but when you refresh, it’s still running — and yes, it will bill 3am-to-noon dead time if you’re not babysitting it.
The culprit here isn’t just inattentiveness — there’s an actual bug where canceling or closing a Chrome tab with the Harvest extension won’t register the pause. And there’s no prompt on session restore. I lost a client over this once because they thought I padded time. They were right, obviously, but not how they thought.
After digging through the dev console, I noticed that the background timer script survives tab closures, which seems like intentional persistence but… probably shouldn’t survive a tab kill if it never hit “start.” Here’s the pattern: if you use keyboard shortcuts to toggle the timer and then immediately close the tab, your pause doesn’t register. Same goes for switching profiles in Edge. Totally undocumented, and scary if you freelance across volatile browser sessions.
I now use an automated Alfred workflow to hard-kill the timer when I lock my screen — crude, but reliable, since native integrations don’t exist. But that shouldn’t be necessary.
2. Toggl loses tracked time blocks when switching between workspaces
Toggl is great until someone adds you to a second client’s workspace and all your active sessions randomly disappear from your sidebar without notice. This happens even if you didn’t switch accounts. Timestamps are there if you dig through your reports manually, but the active timer history wipes itself out from the main UI.
Found this out in the middle of a reconciliation audit with a client who flagged the “missing” entries. Turns out if you toggle between teams under the same account without stopping the timer, it goes orphaned. Not deleted, just untagged and hidden from both views. The way to reveal it? Export as CSV, where it shows up with no project or client tags. Not kidding.
I now run an hourly Checker Zap via zapier.com that queries both workspaces via the GET /time_entries API and confirms all timers have IDs, tags, descriptions, and workspace IDs. If one fails, it pings me in Slack. In a weird twist, the API doesn’t lose the data — just the UI.
This is one of those dev vs marketing disconnections: the system works fine under the hood, it’s just visually misleading during multi-project work. You only find out if you do recon more than once a month.
3. Clockify rate limits too aggressively during bulk edits
Clockify’s API is pretty robust for a free tool — until you try to backfill six days of entries with corrected tags. Found out the hard way there’s an unlisted throttle if you batch PATCH more than 10 edits in under 60 seconds, and it doesn’t return a 429. Just fails silently for everything after edit number ten.
I used Make to build a patcher that would grab all time entries tagged “Misc” and apply proper client and task mappings from Airtable. Worked fine on three projects. Then on a bigger one, everything above entry ID ~40000 just refused to update, no errors. Took me a solid 90 minutes to realize the issue wasn’t permissions — it was hidden throttling.
Fix that actually worked:
Sleep 8 seconds between PATCH requests and chunk by 10 entries per run
The UI will still show the old tags for a while, even though the API shows updates. Cache doesn’t clear reliably — I had to hard reload and clear service workers on desktop. Also, the mobile app NEVER refreshes batch edits. No workaround for that yet.
4. Timing for Mac requires micromanagement to stay useful past week one
I really wanted to love Timing. It has this slick auto-tracking setup where it logs time based on which app or window is active. But here’s the problem: unless you religiously go in and assign each unidentified block to a project, your reports turn to static garbage in about four days — just “Unknown project – Safari” over and over.
Worse, it groups apps as categories like “Browser” or “Communication” instead of actual tasks. If you spend time in Google Docs, it doesn’t know if you’re writing, outlining, or editing — everything is “Docs.” And setting up URL-based filters to distinguish work types sounds smart until you realize all your Google Docs start with the same domain. There’s zero regex support for distinguishing by folder structure, and no G Suite API integration yet for better granularity.
I once spent two hours reassigning untagged time manually because the automatic heuristics lumped Zoom meetings and Netflix together under “Meetings.” Should’ve seen that coming, but still — brutal.
You can get better mileage if you use custom rules per file path or app window title, but it’s not for everyone. Here are a few tricks I use now:
- Watch for “Idle Time” that’s actually screen recording work — it gets wrongfully paused
- Use Terminal command triggers via AppleScript to mark context switches
- Tie Toggl start actions to Timing’s pause so you don’t double-bill
- Exclude apps entirely to reduce clutter (like Discord or music players)
- Manually clear ambiguous time blocks every Friday so they don’t stack
- Export to CSV and slice per filename to rebuild context in Excel
5. RescueTime breaks when used with browser multi-profile setups
Almost undetectable issue unless you look for it: RescueTime silently ignores activity when running in one browser profile if the extension’s installed in another. This might seem obvious, but here’s where it gets weird — the desktop agent doesn’t compensate. If Chrome (Profile A) is hidden while Chrome (Profile B) is active, RescueTime picks up no data. No logs, no system alerts.
I got caught with three dead days in my timeline and only figured out what happened by combing through Activity Monitor. Chrome Helper processes were running fine, but weren’t tied to the active RescueTime thread. Browser process visibility confused it.
Easiest fix? Just run the extension in both profiles. But there’s a Catch-22 — RescueTime will now double count time spent on Gmail (say, 15 mins in each profile shows up as “30 mins Gmail”).
No real workaround unless RescueTime rebuilds its session uniqueness logic. For now, I stripped it down to work only in my general client profile and just don’t let myself watch YouTube from the second.
6. Timery for iOS adds massive value but drains battery hard
Hands down, Timery is the nicest Toggl front-end for iOS. Widgets, shortcuts, Siri voice commands — it’s tight. But something about its background fetch logic goes haywire when paired with iOS Low Power Mode. If you forget and toggle low-power while a project’s running, Timery doesn’t always stop the timer — despite what the UI shows. You’ll think it clocked off, but fifteen hours later, there it is in red.
I once discovered this while boarding a plane. Voice command: “Clock out” — UI paused. Landed seven hours later and it was still live. Battery also halved, despite airplane mode.
I ran instruments on the app and found it polls the Toggl API more aggressively than needed. It’s not supposed to when the timer is idle, but backgroundTasksHandler doesn’t respect idleTimerDisabled settings. iOS doesn’t throw a warning. So I think Timery assumes full API sync even when iOS won’t allow it — and loses confidence in its state, which causes it to misreport status.
No solution yet other than forcing a manual app quit and reopening if toggling energy settings. Or build your own Shortcuts-based confirmation layer, where Scripting checks last update time via API call before allowing sleep mode.