Most solvers make you pick a game before you pick a word — and quietly score everything else with Scrabble values. This free Word Solver does the opposite: enter your letters once, add a board pattern if you are playing onto existing tiles, and choose Scrabble, Words With Friends or Word Chums to see the same rack scored with that game’s real tile values. The rankings genuinely differ, and this solver shows you why.
How the Word Solver works
The solver runs in three modes depending on what you give it. Letters only: it finds every word your tiles can build, the classic rack solve. Pattern only: it finds every word that fits the pattern — letters in their squares, ? for empty squares — and scores each one. Letters plus pattern: the interesting mode. Letters fixed in the pattern are already on the board, so they are free; the empty squares must be filled from your rack, and only those letters are checked against your tiles. In every mode a ? in your letters is a blank tile that can become anything but scores 0, and the game menu swaps the whole scoring table — tile values, not just a label.
Same letters, three different scores
Take the word silent. In Scrabble values it scores 6 — every letter is cheap. Switch the solver to Words With Friends and the identical word scores 8, because that game prices L and N at 2 each. Switch to Word Chums and it scores 9, where L costs 3. Nothing about the word changed except the table judging it, and the effect compounds across a rack: J is worth 8, 10 and 11 across the three games, Q is 10, 10 and 12. A solver that only knows one table will regularly rank your second-best play first in the other two games. This one knows all three, so the answer you get is the answer for the game you are actually playing.
A worked example
Your board shows an R opening a seven-letter slot, and your rack holds ainbow. Set the pattern to r??????, keep your letters in the rack box, choose Scrabble, and the solver returns exactly one word: rainbow, 12 points. The R cost you nothing — it was already on the board — and your six tiles covered the rest precisely. Without the pattern, the same rack yields dozens of shorter words and buries the bingo-class play; the pattern is what turns a rack solver into a board solver.
When to use each mode
Letters-only mode is for open boards and bingo hunting: enter seven tiles and read the longest group first, because playing your whole rack earns the 50-point bonus in Scrabble and Words With Friends. Pattern-only mode is for crossword-style slots and for checking what a tempting board opening could give an opponent. Combined mode is for real mid-game positions — a hook, a parallel lane, a double-word slot with two letters already set. If a combined search returns nothing, loosen it in stages: drop the pattern’s last fixed letter, then check you have not typed a board letter into your rack as well.
Limitations worth knowing
The pattern describes one word in one row; the solver does not model the rest of the board, so premium squares (double and triple letter and word) are not applied — the score shown is the tile total your game will then multiply. Our word list is broader than any game’s official dictionary, so an occasional rare entry may appear that a specific game rejects; common words are always safe. Racks are limited to 12 tiles and patterns to 15 squares, which covers every standard board in the three games.
Word Solver – frequently asked questions
Which games does the Word Solver cover?
Scrabble, Words With Friends and Word Chums, each with its own tile values: switch the game menu and every score and ranking is recomputed with that game’s table.
What does the pattern do that letters alone can’t?
It fixes letters in position. Pattern letters are treated as already on the board — free to use, not drawn from your rack — while ? squares must be filled from your tiles. That is how you solve for a specific slot instead of an open board.
Why does the same word show different scores?
Because the games price tiles differently: L is 1 in Scrabble, 2 in Words With Friends and 3 in Word Chums, for instance. The solver always uses the table of the game you selected.
Does a blank tile in my rack work in pattern mode?
Yes. A ? among your letters is a blank that can fill any empty pattern square, and the letter it covers scores 0, matching the games’ rules.
More word tools and lists
Browse the full collection on our Word Finder & Word Tools hub. See also the Word Unscrambler for a single-game rack solve, the Crossword Solver for pure pattern work, and the Word Chums Cheat if Chums is your game and you want its dedicated filters.
Embed this tool on your website — free
Copy the code below to add this working tool to your own page. A small credit link stays with it — that’s all we ask.
function ilmScoreWord(w, VAL) {
var s = 0;
for (var i = 0; i < w.length; i++) s += VAL[w[i]] || 0;
return s;
}
function ilmRackCounts(rack) {
var counts = {}, wild = 0;
rack = (rack || ”).toLowerCase();
for (var i = 0; i < rack.length; i++) {
var ch = rack[i];
if (ch === ‘?’ || ch === ‘*’) wild++;
else if (ch >= ‘a’ && ch <= ‘z’) counts[ch] = (counts[ch] || 0) + 1;
}
return { counts: counts, wild: wild };
}
// Rack solver: every word buildable from the rack (subset of tiles, ? = blank,
// blank-covered letters score 0), scored with VAL. opts may carry starts,
// ends, contains (lowercase strings) and exactLen (0 = any).
// Returns [{w, s}] sorted length desc, score desc, A-Z.
function ilmRackSolve(rack, words, VAL, opts) {
opts = opts || {};
var rc = ilmRackCounts(rack), counts = rc.counts, wild = rc.wild;
var total = wild;
for (var k0 in counts) total += counts[k0];
var starts = (opts.starts || ”).toLowerCase();
var ends = (opts.ends || ”).toLowerCase();
var contains = (opts.contains || ”).toLowerCase();
var exactLen = opts.exactLen || 0;
var out = [];
for (var j = 0; j < words.length; j++) {
var w = words[j];
if (w.length < 2 || w.length > total) continue;
if (exactLen && w.length !== exactLen) continue;
if (starts && w.indexOf(starts) !== 0) continue;
if (ends && w.slice(w.length – ends.length) !== ends) continue;
if (contains && w.indexOf(contains) === -1) continue;
var need = {};
for (var k = 0; k < w.length; k++) { var c = w[k]; need[c] = (need[c] || 0) + 1; }
var ok = true, deficit = 0, score = 0;
for (var L in need) {
var have = counts[L] || 0;
if (need[L] <= have) score += VAL[L] * need[L];
else {
deficit += need[L] – have;
score += VAL[L] * have;
if (deficit > wild) { ok = false; break; }
}
}
if (ok) out.push({ w: w, s: score });
}
out.sort(function (a, b) {
return b.w.length – a.w.length || b.s – a.s || (a.w < b.w ? -1 : a.w > b.w ? 1 : 0);
});
return out;
}
// Crossword pattern solver: pattern is letters plus ? or . for unknown
// squares. If len is given and longer than the pattern, the pattern is
// padded with ? on the right; if the pattern is longer than len, no match.
// Returns matching words sorted A-Z.
function ilmCrossword(pattern, words, len) {
pattern = (pattern || ”).toLowerCase().replace(/\./g, ‘?’);
var effLen = len || pattern.length;
if (pattern.length > effLen) return [];
var pat = pattern;
while (pat.length < effLen) pat += ‘?’;
var out = [];
for (var j = 0; j < words.length; j++) {
var w = words[j];
if (w.length !== effLen) continue;
var ok = true;
for (var i = 0; i < effLen; i++) {
var p = pat[i];
if (p !== ‘?’ && p !== w[i]) { ok = false; break; }
}
if (ok) out.push(w);
}
out.sort();
return out;
}
// Pattern + rack solver (Word Solver): the word must match the pattern
// positionally; letters on fixed squares are already on the board (free),
// letters on ? squares must come from the rack (? in the rack = blank tile,
// blank-covered letters score 0). Returns [{w, s}] score desc, A-Z.
function ilmPatternRackSolve(rack, pattern, words, VAL) {
pattern = (pattern || ”).toLowerCase().replace(/\./g, ‘?’);
var rc = ilmRackCounts(rack), counts = rc.counts, wild = rc.wild;
var out = [];
for (var j = 0; j < words.length; j++) {
var w = words[j];
if (w.length !== pattern.length) continue;
var ok = true, score = 0;
var needFromRack = {};
for (var i = 0; i < w.length; i++) {
var p = pattern[i];
if (p >= ‘a’ && p <= ‘z’) {
if (p !== w[i]) { ok = false; break; }
score += VAL[w[i]];
} else {
needFromRack[w[i]] = (needFromRack[w[i]] || 0) + 1;
}
}
if (!ok) continue;
var deficit = 0;
for (var L in needFromRack) {
var have = counts[L] || 0;
if (needFromRack[L] <= have) score += VAL[L] * needFromRack[L];
else {
deficit += needFromRack[L] – have;
score += VAL[L] * have;
if (deficit > wild) { ok = false; break; }
}
}
if (ok) out.push({ w: w, s: score });
}
out.sort(function (a, b) {
return b.s – a.s || (a.w < b.w ? -1 : a.w > b.w ? 1 : 0);
});
return out;
}
// Letter filter (Words With Letters): include = letters that must ALL be in
// the word (multiset: "ee" means at least two e’s); exclude = letters that
// must NOT appear. Optional exactLen, starts, ends. Returns words A-Z.
function ilmFilterWords(words, f) {
f = f || {};
var inc = (f.include || ”).toLowerCase();
var exc = (f.exclude || ”).toLowerCase();
var starts = (f.starts || ”).toLowerCase();
var ends = (f.ends || ”).toLowerCase();
var exactLen = f.exactLen || 0;
var incNeed = {};
for (var i = 0; i < inc.length; i++) {
var c0 = inc[i];
if (c0 >= ‘a’ && c0 <= ‘z’) incNeed[c0] = (incNeed[c0] || 0) + 1;
}
var excSet = {};
for (var e = 0; e < exc.length; e++) {
var c1 = exc[e];
if (c1 >= ‘a’ && c1 <= ‘z’) excSet[c1] = true;
}
var out = [];
for (var j = 0; j < words.length; j++) {
var w = words[j];
if (exactLen && w.length !== exactLen) continue;
if (starts && w.indexOf(starts) !== 0) continue;
if (ends && w.slice(w.length – ends.length) !== ends) continue;
var ok = true;
for (var x = 0; x < w.length; x++) if (excSet[w[x]]) { ok = false; break; }
if (!ok) continue;
var wc = {};
for (var y = 0; y < w.length; y++) wc[w[y]] = (wc[w[y]] || 0) + 1;
for (var L in incNeed) if ((wc[L] || 0) < incNeed[L]) { ok = false; break; }
if (ok) out.push(w);
}
out.sort();
return out;
}
// Random picker: opts {count, len (0 = any 2-15), startsWith}. rng() must
// return [0,1). Samples without replacement.
function ilmRandomWords(words, opts, rng) {
opts = opts || {};
var len = opts.len || 0;
var sw = (opts.startsWith || ”).toLowerCase();
var pool = [];
for (var j = 0; j < words.length; j++) {
var w = words[j];
if (len && w.length !== len) continue;
if (sw && w.indexOf(sw) !== 0) continue;
pool.push(w);
}
var count = Math.min(opts.count || 5, pool.length);
var picked = [];
for (var n = 0; n < count; n++) {
var idx = Math.floor(rng() * pool.length);
picked.push(pool[idx]);
pool.splice(idx, 1);
}
return picked;
}
// Scramble: Fisher-Yates shuffle of the word’s letters, retried until the
// result differs from the original (words made of one repeated letter are
// returned unchanged — none are in the game list).
function ilmScrambleWord(word, rng) {
var letters = word.split(”);
var distinct = {};
for (var d = 0; d < letters.length; d++) distinct[letters[d]] = true;
var nDistinct = 0;
for (var k in distinct) nDistinct++;
if (nDistinct < 2) return word;
for (var attempt = 0; attempt < 200; attempt++) {
var a = letters.slice();
for (var i = a.length – 1; i > 0; i–) {
var j = Math.floor(rng() * (i + 1));
var tmp = a[i]; a[i] = a[j]; a[j] = tmp;
}
var s = a.join(”);
if (s !== word) return s;
}
return letters.slice().reverse().join(”);
}
// ~150 common English words for the Word Scramble game (4-8 letters).
var ILM_GAME_WORDS = [‘apple’,’banana’,’orange’,’garden’,’planet’,’silver’,’market’,’window’,’summer’,’winter’,’spring’,’autumn’,’bridge’,’castle’,’dragon’,’friend’,’school’,’pencil’,’paper’,’river’,’ocean’,’forest’,’jungle’,’desert’,’island’,’mountain’,’valley’,’village’,’kitchen’,’bedroom’,’picture’,’camera’,’guitar’,’piano’,’violin’,’trumpet’,’basket’,’bottle’,’candle’,’mirror’,’button’,’pocket’,’ticket’,’travel’,’journey’,’holiday’,’picnic’,’breakfast’,’dinner’,’supper’,’cheese’,’butter’,’coffee’,’sugar’,’pepper’,’lemon’,’melon’,’grape’,’peach’,’mango’,’rabbit’,’turtle’,’monkey’,’tiger’,’zebra’,’panda’,’koala’,’eagle’,’shark’,’whale’,’snake’,’horse’,’sheep’,’chicken’,’spider’,’flower’,’garden’,’hammer’,’ladder’,’rocket’,’planet’,’comet’,’meteor’,’galaxy’,’nebula’,’tunnel’,’harbor’,’anchor’,’sailor’,’pirate’,’treasure’,’diamond’,’golden’,’copper’,’iron’,’steel’,’wooden’,’cotton’,’leather’,’plastic’,’magnet’,’battery’,’engine’,’wheel’,’brake’,’helmet’,’jacket’,’gloves’,’scarf’,’boots’,’socks’,’shirt’,’dress’,’skirt’,’watch’,’clock’,’phone’,’tablet’,’laptop’,’screen’,’keyboard’,’mouse’,’printer’,’speaker’,’dancer’,’singer’,’farmer’,’doctor’,’nurse’,’teacher’,’writer’,’artist’,’baker’,’driver’,’hunter’,’fisher’,’sailor’,’soldier’,’captain’,’general’,’king’,’queen’,’prince’,’knight’,’wizard’,’witch’,’giant’,’fairy’,’elf’,’dwarf’,’goblin’,’troll’,’phoenix’,’unicorn’,’mermaid’,’thunder’,’lightning’,’rainbow’,’snowflake’,’raindrop’,’sunshine’,’moonlight’,’starlight’,’breeze’,’storm’,’cloud’,’fog’,’frost’,’ice’,’snow’,’rain’,’wind’,’wave’,’sand’,’stone’,’rock’,’cliff’,’cave’,’lake’,’pond’,’stream’,’waterfall’,’meadow’,’prairie’,’savanna’,’tundra’,’volcano’,’glacier’,’canyon’,’oasis’,’lagoon’,’coral’,’pearl’,’shell’,’feather’,’wing’,’claw’,’horn’,’tail’,’mane’];
ILM_GAME_WORDS = ILM_GAME_WORDS.filter(function (w, i) { return ILM_GAME_WORDS.indexOf(w) === i; });
if (typeof module !== ‘undefined’) {
module.exports = { ILM_SCRABBLE: ILM_SCRABBLE, ILM_WWF: ILM_WWF, ILM_CHUMS: ILM_CHUMS,
ilmScoreWord: ilmScoreWord, ilmRackSolve: ilmRackSolve, ilmCrossword: ilmCrossword,
ilmPatternRackSolve: ilmPatternRackSolve, ilmFilterWords: ilmFilterWords,
ilmRandomWords: ilmRandomWords, ilmScrambleWord: ilmScrambleWord, ILM_GAME_WORDS: ILM_GAME_WORDS };
}
var WORDLIST_URL = ‘https://ilmhunt.com/wp-content/uploads/2026/10/wordlist.txt’;
var WORDS = null, LOADING = false;
function sendH(){ try { parent.postMessage({wpcId: 5214, wpcH: document.body.scrollHeight + 16}, ‘*’); } catch (e) {} }
window.addEventListener(‘load’, sendH);
function st(msg){ document.getElementById(‘status’).textContent = msg; }
function ensureWords(cb){
if (WORDS) { cb(); return; }
if (LOADING) { return; }
LOADING = true; st(‘Loading the word list (359,039 words)…’);
fetch(WORDLIST_URL).then(function(r){ return r.text(); }).then(function(t){
WORDS = t.split(/\r?\n/).filter(function(x){ return x.length > 0; });
st(‘Word list ready — ‘ + WORDS.length.toLocaleString(‘en-US’) + ‘ words.’);
cb();
}).catch(function(){ LOADING = false; st(‘Could not load the word list. Check your connection and press Solve again.’); });
}
function chips(list, scored){
var html = ”;
list.forEach(function(x){
var w = scored ? x.w : x, s = scored ? x.s : null;
html += ‘<span class="chip">’ + w + (scored ? ‘<sup>’ + s + ‘</sup>’ : ”) + ‘</span>’;
});
return html;
}
function renderGrouped(res, note){
var box = document.getElementById(‘results’);
if (!res.length) { box.innerHTML = ‘<p class="none">No word fits. Check your letters and pattern — one fixed letter in the wrong square hides every play.</p>’; sendH(); return; }
var cap = 1000, shown = res.slice(0, cap), html = ”, curLen = -1;
shown.forEach(function(x){
if (x.w.length !== curLen) {
if (curLen !== -1) html += ‘</div>’;
curLen = x.w.length;
var n = res.filter(function(y){ return y.w.length === curLen; }).length;
html += ‘<div class="grp"><h3>’ + curLen + ‘ letters — ‘ + n + ‘ word’ + (n === 1 ? ” : ‘s’) + ‘</h3>’;
}
html += ‘<span class="chip">’ + x.w + ‘<sup>’ + x.s + ‘</sup></span>’;
});
html += ‘</div>’;
if (res.length > cap) html += ‘<p class="none">Showing the best ‘ + cap.toLocaleString(‘en-US’) + ‘ results.</p>’;
box.innerHTML = html;
st(res.length.toLocaleString(‘en-US’) + ‘ words found. ‘ + note);
sendH();
}
function run(){
ensureWords(function(){
var rack = document.getElementById(‘rack’).value.replace(/[^a-zA-Z?*]/g, ”).slice(0, 12).toLowerCase();
var pat = document.getElementById(‘pattern’).value.replace(/[^a-zA-Z?.]/g, ”).toLowerCase();
var game = document.getElementById(‘game’).value;
var VAL = game === ‘wwf’ ? ILM_WWF : (game === ‘chums’ ? ILM_CHUMS : ILM_SCRABBLE);
var gname = game === ‘wwf’ ? ‘Words With Friends’ : (game === ‘chums’ ? ‘Word Chums’ : ‘Scrabble’);
if (pat && rack) {
renderGrouped(ilmPatternRackSolve(rack, pat, WORDS, VAL), ‘Pattern squares already on the board are free; rack letters fill the rest. Scores: ‘ + gname + ‘ values.’);
} else if (pat) {
var plain = ilmCrossword(pat, WORDS, 0).map(function(w){ return { w: w, s: ilmScoreWord(w, VAL) }; });
plain.sort(function(a, b){ return b.s – a.s || (a.w < b.w ? -1 : 1); });
renderGrouped(plain, ‘Pattern only — every word that fits the squares, best ‘ + gname + ‘ score first.’);
} else if (rack.length >= 2) {
renderGrouped(ilmRackSolve(rack, WORDS, VAL, {}), ‘Scores: ‘ + gname + ‘ values.’);
} else {
st(‘Enter your letters, a pattern, or both.’);
}
});
}
document.getElementById(‘go’).addEventListener(‘click’, run);
document.getElementById(‘rack’).addEventListener(‘keydown’, function(e){ if (e.key === ‘Enter’) run(); });
document.getElementById(‘pattern’).addEventListener(‘keydown’, function(e){ if (e.key === ‘Enter’) run(); });
</script>
</body>
</html>
" style="width:100%;height:620px;border:0;display:block;overflow:hidden;" scrolling="no"></iframe></div>
<p><a href="https://ilmhunt.com/word-solver/" target="_blank" rel="noopener">Word Solver — One Solver for Scrabble, Words With Friends and Word Chums</a> by <a href="https://ilmhunt.com/" target="_blank" rel="noopener">IlmHunt</a> — free online tools</p>
