APCA (Accessible Perceptual Contrast Algorithm) measures the contrast between text and background colours, giving a score roughly between -108 and 106 (the sign just shows which colour is lighter). Higher absolute values mean better contrast: 60+ is good for normal body text, 45+ works for larger text, and anything below about 30 is too low to read comfortably.
Use this palette in JavaScript or Python:
Use this palette in R: