diff --git a/src/core/inputs.ts b/src/core/inputs.ts
index 597e882c..0783fb1b 100644
--- a/src/core/inputs.ts
+++ b/src/core/inputs.ts
@@ -31,6 +31,7 @@ export const anyOf = <New extends InputSource[]>(...args: New) =>
     MapToCapturedGroupsArr<New>
   >
 
+export const between = createInput('[\\w-\\w]')
 export const char = createInput('.')
 export const word = createInput('\\b\\w+\\b')
 export const wordChar = createInput('\\w')
diff --git a/src/core/internal.ts b/src/core/internal.ts
index c72909f2..abf400c0 100644
--- a/src/core/internal.ts
+++ b/src/core/internal.ts
@@ -60,6 +60,10 @@ export interface Input<
       max: Max
     ) => Input<IfUnwrapped<V, `(?:${V}){${Min},${Max}}`, `${V}{${Min},${Max}}`>, G, C>
   }
+  between: <First extends number | string, Last extends number | string>(
+    first: First,
+    last: First extends string ? string : number
+  ) => Input<IfUnwrapped<V, `(?:${V}){${First},${Last}}`, `${V}{${First},${Last}}`>, G, C>
   /** this defines the entire input so far as a named capture group. You will get type safety when using the resulting RegExp with `String.match()`. Alias for `groupedAs` */
   as: <K extends string>(
     key: K
@@ -117,6 +121,8 @@ export const createInput = <
       atLeast: (min: number) => createInput(`${wrap(s)}{${min},}`) as any,
       between: (min: number, max: number) => createInput(`${wrap(s)}{${min},${max}}`) as any,
     }),
+    between: (first: string | number, last: string | number) =>
+      createInput(`[${first}-${last}]`) as any,
     optionally: () => createInput(`${wrap(s)}?`) as any,
     as: groupedAsFn,
     groupedAs: groupedAsFn,
diff --git a/test/index.test.ts b/test/index.test.ts
index 58f88ed3..c3fbe0cf 100644
--- a/test/index.test.ts
+++ b/test/index.test.ts
@@ -74,6 +74,15 @@ describe('inputs', () => {
     expect(pattern.toString()).toMatchInlineSnapshot('"test\\\\/thing"')
     expect(createRegExp(pattern).test('test/thing')).toBeTruthy()
   })
+  it('between', () => {
+    const letterBetween = exactly('').between('c', 'g')
+    expect(letterBetween.toString()).toMatchInlineSnapshot('"[c-g]"')
+    expect(createRegExp(letterBetween).test('abcdefghi')).toBeTruthy()
+
+    const digitBetween = exactly('').between(2, 4)
+    expect(digitBetween.toString()).toMatchInlineSnapshot('"[2-4]"')
+    expect(createRegExp(digitBetween).test('1234567')).toBeTruthy()
+  })
   it('times', () => {
     expect(exactly('test').times.between(1, 3).toString()).toMatchInlineSnapshot('"(?:test){1,3}"')
     expect(exactly('test').times(4).or('foo').toString()).toMatchInlineSnapshot(