Is it possible to get the majority color of an emoji?

An alternative approach without using text-shadow is to copy the emoji, place it directly behind the original and blur it.

You could create the copy directly in the HTML, or if easier use js, as in the example below.

var emoji = document.querySelector("#blur-me");
var copy = emoji.cloneNode(true);
copy.classList.remove("emoji");
emoji.appendChild(copy);
.emoji {
  padding: 3px 6px;
  font-size: 24px;
  position: relative;
  display: inline-block;
}

.emoji span {
  position: absolute;
  left: 6px;
  z-index: -1;
  filter: blur(10px);
}
<span class="emoji" id="blur-me"></span>


An alternative answser to the one proposed by @Sol is to use an attribute to duplicate the icon without the need of JS. You can also apply a scale transformation to make the effect more visible:

.emoji {
  padding: 3px 6px;
  margin:0 5px;
  font-size: 24px;
  position: relative;
  display: inline-block;
  z-index: 0;
}
.emoji:before,
.emoji:after{
  content: attr(data-icon);
}
.emoji:before {
  position: absolute;
  z-index: -1;
  filter: blur(3px);
  transform: scale(1.5);
}
<span class="emoji" data-icon=""></span>
<span class="emoji" data-icon=""></span>
<span class="emoji" data-icon=""></span>
<span class="emoji" data-icon=""></span>


The approach of blurring a copy of the emoji (as proposed by sol) is a valid and fairly lightweight approach. Tweaking it a bit you can get something that is more shadow like:

var emoji = document.querySelector("#blur-me");
var copy = emoji.cloneNode(true);
copy.classList.remove("emoji");
emoji.appendChild(copy);
.emoji {
  padding: 3px 6px;
  font-size: 24px;
  position: relative;
  display: inline-block;
}

.emoji span {
  position: absolute;
  left: 6px;
  z-index: -1;
  filter: blur(5px);
  transform: scale(.95) translate(5px, 5px);
}
<span class="emoji" id="blur-me"></span>

The scale(.95) is to compensate for the blur growing it, and then the translate() is simply to shift it over more like a text shadow and less like a blur.

Another approach which would let you get a more exactly color would be to draw it to a canvas. Once you have a canvas, its basically an image, so those libraries you mentioned could work.

const canvas = document.querySelector('canvas');
canvas.width = 30;
canvas.height = 30;
const ctx = canvas.getContext('2d');
ctx.font = "20px Arial";
ctx.fillText("", 0, 20);
canvas {
  border: 1px solid #000;
}

.emoji {
  text-shadow: rgba(0, 0, 0, .5) 2px 2px 2px;
}
<div class="emoji"></div>
<canvas></canvas>

Once you have that, there are a couple different ways you can get the average. One would be to just get the raw pixels, exclude the background color, and then just mathematically average the remainder. Since canvas is non-transparent, you could use the old-school trick of filling with a really ugly color:

const canvas = document.querySelector('canvas');
canvas.width = 30;
canvas.height = 30;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#121212'; // 12 => 17 in decimal
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.font = "20px Arial";
ctx.fillText("", 0, 20);

const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// an array in the format [r, g, b, count] decimal
const sums = imageData.data.reduce((r, v, i) => {
   if (v === 18) return r; // our fill color, skip
   if (i % 4 !== 3) { // i % 4 === 3 is transparent, ignoring
     r[i % 4] += v;
     r[3]++;
   }
   
   return r;
}, [0, 0, 0, 0]);

sums[3] = sums[3] / 3; // divide by 3 since we counted each pixel 3 times
const averages = [Math.floor(sums[0] / sums[3]), Math.floor(sums[1] / sums[3]), Math.floor(sums[2] / sums[3])];

// just to see the color
ctx.fillStyle = `rgb(${averages.join(',')})`;
ctx.fillRect(0, 0, canvas.width, canvas.height);
canvas {
  border: 1px solid #000;
}

.emoji {
  text-shadow: rgba(0, 0, 0, .5) 2px 2px 2px;
}
<div class="emoji"></div>
<canvas></canvas>

Obviously, this particular algorithm is pretty basic and not perfect (mainly for demo purposes). There are other algorithms or libraries. If you call canvas.toDataUrl() you'll even get a value you can use like an image in most libraries.

From there, just take the calculated color and just use JavaScript to set it to the element.style.textShadow attribute.

document.querySelector('.emoji').style.textShadow = 'rgb(255, 0, 0) 2px 2px';
<span class="emoji"></span>